Grails 2.4.4 HQL for service tests? - unit-testing

I'm trying to create a Grails service test that executes an HQL backed service method (executeQuery). This should now be possible using HibernateTestMixin. However, I am unable to find or create a working example of this. This is what I started with:
#TestFor(FeatureRelationshipService)
#Mock([FeatureRelationship,Feature,Gene,MRNA])
class FeatureRelationshipServiceSpec extends Specification {
this gives me errors about String queries not being supported by GROM (nothing new).
and I changed it to:
#TestFor(FeatureRelationshipService)
#TestMixin([HibernateTestMixin,ServiceUnitTestMixin])
#Domain([FeatureRelationship,Feature,Gene,MRNA])
or
#TestMixin(HibernateTestMixin)
#Domain([FeatureRelationship,Feature,Gene,MRNA])
I get the same error:
Failure: parents for feature(org.bbop.apollo.FeatureRelationshipServiceSpec)
| org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistenceInterceptor': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is java.lang.NullPointerException
at grails.test.runtime.GrailsApplicationTestPlugin$1.initializeContext(GrailsApplicationTestPlugin.groovy:118)

Related

Why does unit test try to find other beans in a controller specific unit test in spring boot

I want to test a single controller which has dependency on 1 service and 1 repo using #WebMvcTest annotation. There are other 5 services/repo in the whole app which i wouldn't want to mock in this unit test.
I have mocked the required 2 services/repo. Here i am testing a simple endpoint which doesn't even access the repo but when i try to unit test this controller for that specific controller in spring boot like this
#RunWith(SpringRunner.class)
#WebMvcTest(WebController.class)
public class LoginTest {
#MockBean
private CustomerRepository customerRepository;
#MockBean
private CustomerService customerService;
private MockMvc mockMvc;
#Test
public void serverRunning() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(content().string("Server is running"))
.andDo(print());
}
}
I get
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restaurantRequestRepository': Cannot create inner bean '(inner bean)#60b4d934' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#60b4d934': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
Note: If i use #SpringBootTest, it works but i don't want to instantiate the whole application for a simple test.
I ran into exactly the same problem. This was caused by having the #EnableJpaRepositories annotation on my main Spring app class. The webmvc test disables full auto-configuration, but must still load the base application class.
Easy fix, fortunately, simply create a new configuration class and move your #EnableXRepository annotations to that class instead, and they won't be included in your webmvc test!
#Configuration
#EnableJpaRepositories
class PersistenceConfiguration {}

"Method threw 'java.lang.LinkageError' exception" while calling a stub method

I am trying to call a method of a web service using an auto generated stub.
At following line it assigns,
Method threw 'java.lang.LinkageError' exception. Cannot evaluate org.apache.axiom.soap.impl.llom.soap11.SOAP11BodyImpl.toString()
as the SOAP envelope.
env = toEnvelope(getFactory(_operationClient.getOptions().getSoapVersionURI()),
simpleQueryInput587,
dummyWrappedType,
optimizeContent(new javax.xml.namespace.QName("http://docs.oasis-open.org/ns/bpel4people/ws-humantask/api/200803",
"simpleQuery")));
what is the reason for this?
This was caused since same package has been exported by two jars.

Spring XD (Spring Integration DSL based) AWS S3 sink module error

I'm trying to build a Spring XD (Spring Integration DSL based) sink module using the spring-integration-aws extension. My module looks like so:
#Configuration
#EnableIntegration
public class S3Module {
#Value("${accessKey:myAccessKey}")
private String accessKey;
#Value("${secretKey:mySecretKey}")
private String secretKey;
#Value("${bucket:myBucket}")
private String bucket;
#Value("${remoteDirectoryExpression:dir}")
private String remoteDirectoryExpression;
#Bean
public AmazonS3MessageHandler handle() {
AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
AmazonS3MessageHandler handler = new AmazonS3MessageHandler(credentials, new DefaultAmazonS3Operations(credentials));
handler.setBucket(bucket);
handler.setRemoteDirectoryExpression(new LiteralExpression(remoteDirectoryExpression));
return handler;
}
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from("input")
.handle(handle())
.get();
}
}
I can successfully package up the module and deploy it. When trying to create the stream with:
xd:>stream create --name s3test --definition "file --outputType=text/plain --dir='/tmp/logs' | s3" --deploy
I get the following exception:
00:25:28,850 1.1.0.RC1 INFO DeploymentSupervisor-0 server.StreamDeploymentListener - Deployment status for stream 's3test': DeploymentStatus{state=failed,error(s)=org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flow' defined in com.test.xd.S3Module: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'flow' threw exception; nested exception is java.lang.ClassCastException: com.sun.proxy.$Proxy145 cannot be cast to org.springframework.integration.aws.s3.AmazonS3MessageHandler
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'flow' threw exception; nested exception is java.lang.ClassCastException: com.sun.proxy.$Proxy145 cannot be cast to org.springframework.integration.aws.s3.AmazonS3MessageHandler
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 36 more
Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy145 cannot be cast to org.springframework.integration.aws.s3.AmazonS3MessageHandler
at com.test.xd.S3Module$$EnhancerBySpringCGLIB$$8623ddbe.handle(<generated>)
at com.test.xd.S3Module.flow(S3Module.java:49)
at com.test.xd.S3Module$$EnhancerBySpringCGLIB$$8623ddbe.CGLIB$flow$1(<generated>)
at com.test.xd.S3Module$$EnhancerBySpringCGLIB$$8623ddbe$$FastClassBySpringCGLIB$$3453fd21.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
at com.test.xd.S3Module$$EnhancerBySpringCGLIB$$8623ddbe.flow(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 37 more
I'm fairly certain I'm missing something simple. Can someone point me in the right direction? Thanks in advance!
Thank you for doing such a work! Yes, definitely we'll introduce somedays out-of-the-box AWS modules to XD.
Your issue is similar to this one: https://github.com/spring-projects/spring-boot/issues/2441#issuecomment-72758919.
To overcome that you just should do:
#Bean
public MessageHandler handle() {
make return type as an interface not target class. That's because Spring Integration JMX exposing feature is switched on by default in XD.
Out of topic: we are going to break SI-AWS soon and make it based on the Spring Cloud AWS. And I think that that AWSCredentials stuff will be removed in favor of standard AWS CredentialsProvider. So, there will be a lot of breaking changes for the SI-AWS 1.0.0.

Facing Issue with Unit testing in Grails

I need to get messagesource to get access message.properties file in simple groovy class(Exception class) so that i am using Holders.getGrailsApplication(). My problem is Holders.getGrailsApplication() is getting null when i execute unit test case.It works fine if i deploy it in web server.
Variable :-
static def grailsApplicationCntx=Holders.getGrailsApplication().getMainContext().getBean(‘messageSource’)
Error:-
`Failure: testActivateService_Case1(com.xyz.ActivationServiceTests)
| java.lang.ExceptionInInitializerError
at java.lang.Class.forName(Class.java:186)
at com.xyz.DatabaseService.addBankUser(DatabaseService.groovy:11)
at com.xyz.RegisterService.register(RegisterService.groovy:39)
at com.xyz.ActivationServiceTests.setUp(ActivationServiceTests.groovy:60)
Caused by: java.lang.NullPointerException: Cannot invoke method getMainContext() on null object
at com.xyz.exception.Exception.(Exception.groovy:55)
… 4 more
I think no need to inject messageSource. It is already available there.Just use
messageSource.addMessage("foo.bar", request.locale, "My Message")

How to access EJB services from a grails standalone client

I've been having problems to access to my EJB services from a standalone client i've developed on grails 2.0.3. The EJB services are deployed on a glassfish server (Java). I tested this code on a netbeans tester class to access the EJBs:
Properties p = new Properties();
p.put("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
p.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
p.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
p.setProperty("org.omg.CORBA.ORBInitialHost", INTEGRATION_IP);
p.setProperty("org.omg.CORBA.ORBInitialPort", CORBA_PORT);
ctx = new InitialContext(p);
try {
this.admAuth = (AdmAuthenticationRemote) this.ctx.lookup(Tester.AUTHENTICATION_SERVICE_JNDI);
}catch(Exception e){
...
}
This Tester.AUTHENTICATION_SERVICE_JNDI is a variable tha contains the path to the deployed service, in this case something like "java:global/..." that represents the address to the service that is being requested. This way of accessing the services works perfectly from the tester, but when i try to do the same from grails doesn't works. I am able to create the context the same way, but when i invoke the ctx.lookup() call i get an exception:
Message: Lookup failed for 'java:global/...' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory,
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
Cause: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory,
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
[Root exception is java.lang.RuntimeException: Orb initialization erorr]
The main exception is a naming exception, which means that it failed in the ctx.lookup(), but the cause is the orb initialization exception, which has another exception stack:
java.lang.RuntimeException: Orb initialization erorr
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
Caused by: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
I'm really lost here. I've been having a lot of problems to get this going on grails, I had to get all glassfish jars (libs and modules) so it could make the InitialContext() call, but now i'm not sure if this is still a jar problem or a configuration problem or what it is.
I know that IllegalArgumentException occurs when u try to assign incompatible types in java, but i'm not setting anything like that, so i assume its an internal method initialization.
So the question is why is this exception coming up??
Is there another way to invoke my services from grails that works better??
The error is that you're trying to run your web application using the tomcat plugin in grails (using the command grails run-app). The problem is that when you try to create the InitialContext (com.sun.enterprise.naming.SerialInitContextFactory) groovy gives you an error casting some types if you're using the client libraries for GF 3.1. (I know that this is the problem, but I really don't know the reason for this. Because in theory this should work)
If you generate the .war file and you deploy in an AppServer, you can connect to your EJBs without problems. And if you deploy it on another GF server you don't have to import any of the client jars.
This will work perfect on production, the only problem is that you must compile and deploy your app on the GF server with every little change, and this is a bit annoying in development.
If you want to work outside of GF and using the command "grails run-app", you must modify two of the .jar GF 3.1 on your remote server, where you have the grails application:
1- The jar file $GLASSFISH_HOME/modules/glassfish-corba-omgapi.jar
You should search in the web the class com.sun.corba.ee.spi.orb.ParserImplBase, and modify this part
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
for this
if (name.equalsIgnoreCase("waitForResponseTimeout")) {
Object newValue = new Long(1800000);
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, newValue);
} else {
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
}
this should resolve the java.lang.IllegalArgumentException
2- The jar file $GLASSFISH_HOME/modules/glassfish-corba-orb.jar
you must delete the javax.rmi.CORBA.PortableRemoteObjectClass class of this library, because this class have conflicts with one used by the grails plugin
PS:
If you do not want to have the GF client jars in your grails application, you can add to the classpath of your client machine the following libraries
$GLASSFISH_HOME/modules/ejb-container.jar
$GLASSFISH_HOME/modules/ejb.security.jar
$GLASSFISH_HOME/modules/management-api.jar
If you use the grails console with the grails run-app command, must modify the configuration file $GRAILS_HOME/conf/groovy-starter.conf whit this
load $GLASSFISH_HOME/modules/ejb-container.jar
load $GLASSFISH_HOME/modules/ejb.security.jar
load $GLASSFISH_HOME/modules/management-api.jar