Invoking groovy method in Mule 4 - groovy

I have built a complete groovy project with JPA repo for data persistence operations. Now I want to invoke the methods from the script in Mule 4 without changing anything in the groovy project.
eg. CustomerService.groovy (pseudo code)
import com.example.dao.CustomerDao.groovy
... other imports...
#Service
class CustomerService {
#Autowired
CustomerDao cDao
#Transactional
publid Customer createCustomer(Customer customer) {
return cDao.save(customer)
}
... other methods...
}
CustomerDao.groovy
import spring.JPA (the original import path may vary)
#Repository
class CustomerDao implements JPARepository<Customer, Integer> {
}
This project is working in Mule 3. In Mule 3 we have an Invoke component which could be used to invoke the methods from the groovy script. The Mule 4 the Invoke component is compatible only with Java and not groovy.
The Scripting module's 'Execute' component can invoke a groovy script but not sure how to invoke the method. Is the any work around for this in Mule 4?
Problems occured as of now
In 'Execute' component if I import another file I get the error as
Unalbe to resolve class com.example.dao.CustomerDao
# line 3 column 1,
import com.example.dao.CustomerDao.groovy
^
Found a solution for similar problem https://help.mulesoft.com/s/article/Compilation-exception-in-Mule4-x-when-using-Groovy-script-with-Import-statement but unable to implement it.
In the article, he developer had an issue with an apache dependency, which he/she could get from mvn repo. I am trying to import a groovy file which I have developed. So unable to add it in the dependency. I tried adding the groovy project in my local repo and fetch it but it didn't work. Moreover, when this Mule 4 application will be deployed on CloudHub it will have an issue as it won't be able to access my local repo.
Need a solution to add a spring-groovy project to Mule 4
Thanks :)

The problem is that the Groovy script executed by the Scripting Module is trying to import a class, which is not in Java's classpath. So it throws the error. The class is in another Groovy source file. What you can do is to compile the Groovy code into an actual Java class. You can try one the methods described in the Groovy documentation to integrate a Maven plugin with your Mule application pom.xml file.
Another alternative if you have a large number of Groovy classes is to create a separate project to build a Jar library, then use the solution from the KB article you mentioned.

Related

How to use Micronaut & depenency injection in a single-file Groovy script?

I want to use Micronaut from a Groovy script. It seems that annotations such as #Inject and #PostConstruct are not processed.
Here is the code I tried:
#!/usr/bin/env nix-shell
#!nix-shell -i groovy
#Grapes([
#Grab('ch.qos.logback:logback-classic'),
#Grab('io.micronaut:micronaut-runtime')
])
package org.sdf // NPE without package
import io.micronaut.runtime.Micronaut
import javax.inject.*
import javax.annotation.*
#Singleton
class Component {
}
#Singleton
class App implements Runnable {
#Inject
Component comp
#Override
#PostConstruct
public void run() {
// Never runs
assert this.comp != null
assert false
}
}
static void main(String... args) {
Micronaut.run(App, args);
}
It doesn't run post-construct method and logs this:
22:17:43.669 [main] DEBUG i.m.context.DefaultBeanContext - Resolved bean candidates [] for type: interface io.micronaut.runtime.EmbeddedApplication
22:17:43.671 [main] INFO io.micronaut.runtime.Micronaut - No embedded container found. Running as CLI application
How can I use Micronaut with dependency injection in a single-file Groovy script?
How can I use Micronaut with dependency injection in a single-file
Groovy script?
You would have to compile all of the code in your script with Micronaut's annotation processors configured on the compile time classpath for your script. Technically that could be done with a single script but as a practical matter I don't think many folks are going to have a good reason to do or build support for making that more easily done.
FYI: Not an answer to your question as asked but one simple alternative approach is to not define all of your bean related classes in a single script, instead define them in their own separate source files in a project configured to build with Maven or Gradle using our annotation processors and then consume those classes from your script using #Grab like you have for other dependencies.

Is additional context configuration required when upgrading cucumber-jvm from version 4 to version 6?

I am using cucumber-jvm to perform some functional tests in Kotlin.
I have the standard empty runner class:
#RunWith(Cucumber::class)
#CucumberOptions(features=[foo],
glue=[bar],
plugin=[baz],
strict=true,
monochrome=true)
class Whatever
The actual steps are defined in another class with the #ContextConfiguration springframework annotation.
This class also uses other spring features like #Autowire or #Qualifier
#ContextConfiguration(locations=["x/y/z/config.xml"])
class MyClass {
...
#Before
...
#Given("some feature file stuff")
...
// etc
}
This all work fine in cucumber version 4.2.0, however upgrading to version 6.3.0 breaks things. After updating the imports to match the new cucumber project layout the tests now fail with this error:
io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.
It provides examples of what it means...
For example:
#CucumberContextConfiguration
#SpringBootTest(classes = TestConfig.class)
public class CucumberSpringConfiguration {}
Or:
#CucumberContextConfiguration
#ContextConfiguration( ... )
public class CucumberSpringConfiguration {}
It looks like it's telling me I can just add #CucumberContextConfiguration to MyClass.
But why?
I get the point of #CucumberContextConfiguration, it's explained well here but why do I need it now with version 6 when version 4 got on fine without it? I can't see any feature that was deprecated and replaced by this.
Any help would be appreciated :)
Since the error matches exactly with the error I was getting in running Cucumber tests with Spring Boot, so I am sharing my fix.
One of the probable reason is: Cucumber can't find the CucumberSpringConfiguration
class in the glue path.
Solution 1:
Move the CucumberSpringConfiguration class inside the glue path (which in my case was inside the steps package).
Solution 2:
Add the CucumberSpringConfiguration package path in the glue path.
The below screenshot depicts my project structure.
As you can see that my CucumberSpringConfig class was under configurations package so it was throwing me the error when I tried to run feature file from command prompt (mvn clean test):
"Please annotate a glue class with some context configuration."
So I applied solution 2, i.e added the configurations package in the glue path in my runner class annotation.
And this is the screenshot of the contents of CucumberSpringConfiguration class:
Just an extra info:
To run tests from command prompt we need to include the below plugin in pom.xml
https://github.com/cucumber/cucumber-jvm/pull/1959 removed the context configuration auto-discovery. The author concluded that it hid user errors and removing it would provide more clarity and reduce complexity. It also listed the scenarios where the context configuration auto-discovery used to apply.
Note that it was introduced after https://github.com/cucumber/cucumber-jvm/pull/1911, which you had mentioned.
Had the same error but while running Cucumber tests from Jar with Gradle.
The solution was to add a rule to the jar task to merge all the files with the name "META-INF/services/io.cucumber.core.backend.BackendProviderService" (there could be multiple of them in different Cucumber libs - cucumber-java, cucumber-spring).
For Gradle it is:
shadowJar {
....
transform(AppendingTransformer) {
resource = 'META-INF/services/io.cucumber.core.backend.BackendProviderService'
}
}
For Maven something like this:
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/io.cucumber.core.backend.BackendProviderService</resource>
</transformer>
</transformers>
A bit more explanation could be found in this answer

Unit Testing with groovy

New to groovy and java. Installed groovy,plugin with eclipse and created a groovy project
I am able to run groovy scripts and groovy class. But GroovyTestCase class is not getting resolved. Any help is appreciated.
package p1
import groovy.util.GroovyTestCase
class MyTest extends GroovyTestCase { //GroovyTestCase keyword is showing this error: type junit.framework.TestCase cannot be resolved. It is indirectly referred from required .class files
void testSomething() {
assert 1 == 1
assert 2 + 2 == 4 : "We're in trouble, arithmetic is broken"
}
}
GroovyTestCase is JUnit 3, If you want to use Junit4, don't extend the class, instead use the #Test annotations like in Java.
You can use JUnit as it was pointed out before, but on Groovy usually the library that it is used it is called Spock. Next question would be Why Spock, then check this out.
We have been using it for a while, and it works like a charm. Highly recommended.

How do I know at runtime which implementing classes are set for my Spring beans?

In hybris, is there an easy way to know which implementing class is being used for a certain Spring bean?
I mean, I can override a Bean by doing something like this:
<alias name="myCheckoutFacade" alias="checkoutFacade"/>
<bean id="myCheckoutFacade" class="com.pedra.facades.checkout.impl.MyCheckoutFacadeImpl" scope="tenant" parent="defaultCheckoutFacade">
<property name="commerceCheckoutService" ref="myCommerceCheckoutService"/>
</bean>
... so now when Spring needs to create a bean with the alias checkoutFacade the implementing class will be MyCheckoutFacadeImpl as opposed to the overridden defaultCheckoutFacade which was defined in some other xml configuration file.
So is there a way to know at runtime which implementing class is being used for a certain Spring bean definition? Without having to debug the code, I mean.
Beanshell or Groovy :-)
Checking the implementing class of a bean is just one of the many cool things you can do at runtime with Beanshell or Groovy.
Disclaimer: Be careful running Beanshell or Groovy code on a production machine!
Log in to the HAC and go to Console > Beanshell or Groovy
Execute the following code in either Beanshell or Groovy to get your implementing class:
de.hybris.platform.core.Registry.getApplicationContext().getBean("checkoutFacade");
Both consoles will show the result of the last expression in the Result tab.
In the Groovy console for Hybris 5.x, simple execute the following:
checkoutFacade
As you can see, each bean is automatically def-ed into each Groovy script.
As for Beanshell, you could create a bean function in Beanshell:
import de.hybris.platform.core.Registry;
import de.hybris.platform.commercefacades.order.CheckoutFacade;
Object bean(String beanName)
{
return Registry.getApplicationContext().getBean(beanName);
}
CheckoutFacade checkoutFacade = (CheckoutFacade) bean("checkoutFacade");
print(checkoutFacade);
I ended up using Beanshell so much that I created my own wrapper application that allows me to develop Beanshell in Eclipse, and use Eclipse as the Beanshell console. But that's a whole other post!
Resources:
Beanshell User Manual
Beanshell Commands Documentation (Built-in functions like print())

How to define a global class in SoapUI as a groovy script?

I want to define a class in a groovy script that i could reuse trough other groovy script inside SoapUI.
I alredy tried to define my class inside a TestSuite property but it doesn't work. I would like to avoid defining the class in a JAR because we work in team and every one would have to import the JAR in their SoapUI in order to run my tests. I use SoapUI 3.6.1
Here's how my TestSuite is made :
TestSuite
TestCase
TestSteps
Init (Groovy Script)
GetResponse1 (Test Request)
Test1 (Groovy Script)
GetResponse2 (Test Request)
Test2 (Groovy Script)
To simplify me tests, i defined a class in 'Test1' and i would like to reuse this class in 'Test2'. So ideally i would define that class in 'Init' and it would be accessible to any other groovy script.
How can i achieve that?
Based on #Abhey Rathore's link, here is how to define a global class in SoapUI's groovy script:
Step 1: Declare the global class
Create a project called MyRepository
Under this project create a disabled TestSuite called lib
Under this test suite create a TestCase called MyClass
Under this test case create a groovy script called class
Your project tree should look like the image below:
Step 2: Write the global class code
Inside the groovy script called class, copy and and paste the code below:
class MyClass {
// The three following fields are MANDATORY
def log
def context
def testRunner
// The constructor below is MANDATORY
def MyClass(logIn, contextIn, testRunnerIn) {
this.log = logIn
this.context = contextIn
this.testRunner = testRunnerIn
}
def myMethod() {
this.log.info 'Hello World!'
}
}
// Other scripts elsewhere in SoapUI will access the reused class through their context
context.setProperty( "MyClass", new MyClass(log, context, testRunner) )
Step 3: Import the global class
From any project, you can import the global class by using the following snippet:
// Import the class
def currentProject = testRunner.testCase.testSuite.project
currentProject
.testSuites["lib"]
.testCases["MyClass"]
.testSteps["class"]
.run(testRunner, context)
// Now use it
context.MyClass.myMethod()
SoapUI 5.2.1
try this, I think will help you in reusable code.
http://forum.soapui.org/viewtopic.php?t=15744
I am pretty sure that you will have to create a JAR file and put it in \bin\ext.
SoapUI will automatically pick it up on restart (you should see it mentioned in the startup stuff).
You basically just create a Java or Groovy project, Export it (with Eclipse) and it will work. SoapUI will probably have your dependencies covered, but if not you can add those JARs too (safer than creating a runnable JAR since SoapUI might use different versions of what you use).
If you need help, post related questions.
In SoapUI 5.3.0 you can use properties that can be set and get on the context variable. That variable is available in script assertion snippet.
For example:
context.setProperty("prop", "value");
And from different test script you can get the value by:
context.getProperty("prop");
You can use the property from when you define property as a step of test suite or as a value for field in header. You can do it by ${=context.getProperty("prop");}
Write this into your Project's load script, then reload your project or just run it.
com.eviware.soapui.support.ClasspathHacker.addFile( project.context.expand('${projectDir}') )
After it has run, you can now put .groovy files into the same folder as your soapui project xml. Plus, there is no need to compile anything.
e.g. in MyClass.groovy:
class MyClass {String name}
You can import those classes as normal in all your other scripts:
import MyClass
assert new MyClass(name:"me") instanceof MyClass
The only caveat is that your load script (the one setting the classpath), cannot have those imports, because the script will fail to compile. If you want to import something during your project load script, just have your load script 'evaluate' another groovy script (in other words, run it), in which you can use the imports:
evaluate (new File (project.context.expand('${projectDir}') + 'myProjectLoadScript.groovy'))
//in myProjectLoadScript.groovy:
import MyClass
/* Do things using MyClass... */
This seems the easiest way to me, so I'm not sure why I couldn't find this answer elsewhere online.

Resources