Arquillian Spring Tomcat 7 embedded - mock #Configuration class - java

I'm working on a multi-module maven project, and I'm trying to integrate arquillian in it to ease development and create some integration tests.
I'm using Tomcat 7 embedded, and I got to a point where everything works.
Now I want one of the classes that are injected in a service to be mocked. When I'm debugging (using Intellij Idea) everything seems to be working nice... my test #Configuration class (ApplicationConfig2) is added to the WAR, it injects a Dummy object which is later used by the service.
The problem is when running the same test using maven (clean install) (surefire plugin) it tells me an error occurred.
Here's my deployment:
#Deployment(testable = false)
public static WebArchive createTestArchive() {
File[] files = Maven.resolver()
.offline()
.loadPomFromFile("pom.xml")
.resolve("org.glassfish.jersey.containers:jersey-container-servlet-core:2.6",
"com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.1"
)
.withTransitivity()
.asFile();
return ShrinkWrap
.create(WebArchive.class, "ROOT.war")
.addClass(Controller.class)
.addClass(Service.class)
.addClass(SomeObjectInterface.class)
.addClass(MockedSomeObjectImpl.class)
.addClass(MyApplication2.class)
.addClass(ApplicationConfig2.class)
.addClass(MyWebAppInitializer2.class)
.addAsLibraries(files)
.setWebXML("in-container-web.xml");
}
Here's my web app initializer used in tests:
#Order(Integer.MIN_VALUE)
public class MyWebAppInitializer2 implements WebApplicationInitializer {...}
I have another one named MyWebAppInitializer which is used by the "real" WAR module.
The error that I get is :
INFO: Spring WebApplicationInitializers detected on classpath: [foo.MyWebAppInitializer#1e194cf1, foo.MyWebAppInitializer2#f0a71a7, org.glassfish.jersey.server.spring.SpringWebApplicationInitializer#76ab92a7]
Aug 11, 2015 4:50:34 PM org.apache.catalina.core.ApplicationContext log
So, for some reason, even if I don't include the class MyWebAppInitializer in the web archive, it seems it is loaded by Tomcat even the same. I'm checking the generated WAR package, and the only class present is MyWebAppInitializer2 (the testing one), and not MyWebAppInitializer.
Am I missing something?

From what I found out... nobody should use the embedded containers, as they are unreliable.

Related

Using SpringExtension with Tomcat and Hibernate web app

We are trying to use spring-test's SpringExtension to write integration tests for our Spring and Hibernate-based Tomcat web application. Our sessionFactory bean configuration has the property configured mappingJarLocations with a sample value as /WEB-INF/lib/company-common*.jar which contains hibernate mapping files. In both actual deployment and Eclipse dev deployment, this works fine as the docBasePath (in Servlet environment) is appended to this pattern and the files are getting resolved. But this is not the case while running JUnit test cases either in a local or a CI environment.
We tried our best to use the provided support by having few overridden implementations of WebTestContextBootstraper, GenricXmlWebContextLoader, XmlWebApplicationContext, and WebDelegatingSmartContextLoader but had to finally give up as we cannot override the final method org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(MergedContextConfiguration) to provide the custom implementation of XmlWebApplicationContext. Our current approach is to manually create the application context and use it in the tests.
Here is the project structure:
Project_WebApp
|--src/**
|--WebContent/**
|--pom.xml
When the app is packaged as Project_WebApp.war, the dependencies are inside WEB-INF/lib from the root of extracted war. When deployed as a webapp in Tomcat using Eclipse, the dependencies are copied to <Eclipse_Workspace_Dir>/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/Project_WebApp/WEB-INF/lib. In both cases, the dependencies are available at <Resource_Base_Path>/WEB-INF/lib and Resource_Base_Path has no relation to Project_WebApp base directory.
Questions:
Did any one use SpringExtension in a scenario similar to above? If so can you suggest any alternative approaches?
Instead of /WEB-INF/lib/company-common*.jar, we tried a classpath-based pattern but didn't work as the obtained class path resources don't match the pattern. Is there anything else to try here?

How does Java runtime find my main class?

I am learning Spring Boot. I made a simple Spring Boot project that can output a hello world string at http://localhost:8080/welcome
I use Maven to build my project that would output a jar file.
To start up my spring boot app, I use the command as below
java -jar my-springboot-app.jar
My question is:
How is java smart enough to locate my main class and its main method (e.g. the application launcher)?
I checked the jar file and browsed those BOOT-INF & META-INF and could not find any clues.
Does the spring boot framework (#SpringBootApplication) or maven automatically do the magic for me?
In case of spring boot jar the things are little bit more complicated than regular jar. Mainly because spring boot applicaton jar is not really a JAR (by jar I mean something that has manifest and compiled classes). Regular JARs can be "recognized" and processed by jvm, however in Spring Boot there are also packed dependencies (take a look at BOOT-INF/lib) so its jars inside JARs. How to read this?
It turns out that spring boot always has its own main class that is indeed referred to in MANIFEST.MF and this a real entry point of the packaged application.
The manifest file contains the following lines:
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.demo.DemoApplication
Main-Class is a JVM entry point. This class, written by spring developers, basically does two things:
- Establishes a special class loader to deal with a "non-regular-jar" nature of spring boot application. Due to this special class loaders spring boot application that contains "jars" in BOOT-INF/lib can be processed, for example, regular java class loaders apparently cannot do this.
- Calls the main method of Start-Class value. The Start-Class is a something unique to spring boot applications and it denotes the class that contains a "main" method - the class you write and the class you think is an entry point :) But from the point of view of the spring boot infrastructure its just a class that has an "ordinary" main method - a method that can be called by reflection.
Now regarding the question "who builds the manifest":
This MANIFEST.MF is usually created automatically by plugins offered by Spring Developers for build systems like Maven or Gradle.
For example, the plugin looks like this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
During its work, this plugin identifies your main class (com.example.demo.DemoApplication in my example). This class is marked with #SpringBootApplication annotation and has a public static void main method.
However, if you put many classes like this the plugin probably won't recognize the correct class so you'll need to configure the plugin properties in POM.xml to specify the right class.
Java classes are executed within a larger context,
you run java -jar somejar.jar the class in question will be selected in the .jar file's manifest.
#SpringBootApplication will have componentscan, enabling auto configuration(autowired)
componentscan - to identify all the controller, service and configuration classes within the package.

How to add classes from another to the Arquillian deployment archive?

I'm getting started with Arquillian and followed the tutorial. It covers how to inject EJBs into a test case. Since Arquillian is targeting Java Web and EE projects, I'm very suprised that the separation of entity classes and EJB interfaces wasn't covered in the tutorial since at least EE projects where everything is dumped in one project are rare.
Since there's no coverage in the tutorial and no understandable error message by any of the EE containers, I managed to extract a test case by trial and error which shows that classes used in
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class)
.addClasses(MyXBean.class, DefaultMyXBean.class, TermsOfUse.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
which are on the classpath, but not in the same Maven project the test in contained in, fail due to NoClassDefFoundError. Moving the class into the project without touching anything else makes the deployment work.
Is there any way to use Arquillian in a "real" Java EE in which entities and interfaces are not contained into the .war of the test, but as a sibling inside the parent .ear archive of the .war?
I could think of adding JARs from the Maven cache with hardcoded pathes, but that can't be it, can it?
How test in Java ee using Arquillian maven multiple project might be about the same issue.
An EAR deployment with libraries can be built like this:
#Deployment
public static Archive<?> createDeploymentPackage() throws IOException {
MavenDependencyResolver resolver = DependencyResolvers
.use(MavenDependencyResolver.class)
.loadMetadataFromPom("test1-pom.xml");
final JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "my-ejbs.jar").addClass(SomeEjb.class);
final WebArchive webApp = ShrinkWrap.create(WebArchive.class, "my-webap.war").addClass(MyServlet.class);
final EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class)
.setApplicationXML("application.xml")
.addAsLibraries(resolver.artifact("log4j:log4j:1.2.17").resolveAsFiles())
.addAsModule(ejbJar)
.addAsModule(webApp);
return ear;
}

How to deploy a Spring Boot application on Weblogic 12c (12.1.3)?

I'm trying to deploy a simple Spring Boot application on Weblogic 12c (12.1.3), in a developer environment it does work perfectly.
However when need to repackage it in a war and to attach it to an earand this does not seem to deploy correctly.
This is the stacktrace:
<Nov 23, 2016 6:15:13 PM CET> <Error> <Munger> <BEA-2156200> <Unable to load descriptor weblogic.utils.classloaders.GenericClassLoader#6964c078 finder: weblogic.utils.classloaders.CodeGenClassFinder#5715556 annotation: my-app-ear#/WEB-INF/lib/tomcat-embed-websocket-8.5.6.jar!/META-INF/web-fragment.xml of module /my-app. The error is weblogic.descriptor.DescriptorException: Unmarshaller failed
Any input will be very welcome.
Thanks in advance.
From Spring Boot docs,
To deploy a Spring Boot application to WebLogic you must ensure that
your servlet initializer directly implements WebApplicationInitializer
(even if you extend from a base class that already implements it).
For Example,
Change this,
public class Application extends SpringBootServletInitializer {
to
public class Application extends SpringBootServletInitializer implements WebApplicationInitializer {
NOTE: SpringBootServletInitializer already implements WebApplicationInitializer, but you need to do it again.
As of now,I don't know Why.
public abstract class SpringBootServletInitializer implements WebApplicationInitializer {
From Spring source code,
You need to do 2 things:
On your weblogic 12.1.3 instance, upgrade your JPA api and add the hibernate 5 implementation
In you web app, make sure what dependencies you have and that they do not overlap with the ones already provisioned under Weblogic classloader.
I have details the steps here:
http://javagoogleappspot.blogspot.be/2018/05/make-your-spring-boot-20-compatible.html

Classloader problem with EJB

I'm working on a project which includes persistence library (JPA 1.2), EJB 3 and Web presentation layer (JSF). I develop application using Eclipse and application is published on Websphere Application Server Community Edition (Geronimo 2.1.4) through eclipse plugin (but the same thing happens if I publish manually). When publishing to server I get the following error:
java.lang.NoClassDefFoundError: Could not fully load class: manager.administration.vehicles.VehicleTypeAdminBean
due to:manager/vehicles/VehicleType
in classLoader:
org.apache.geronimo.kernel.classloader.TemporaryClassLoader#18878c7
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:177)
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:146)...
In web.xml I have reference to EJB:
<ejb-local-ref>
<ejb-ref-name>ejb/VehicleTypeAdmin</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>manager.administration.vehicles.VehicleTypeAdmin</local>
<ejb-link>VehicleTypeAdminBean</ejb-link>
</ejb-local-ref>
EJB project has a reference to persistence project, and Web project has references to both projects. I don't get any compilation errors, so I suppose classes and references are correct.
I don't know if it is app server problem, but I ran previously application on the same server using same configuration parameters.
Does anybody have a clue what might be the problem?
Looks almost like it couldn't find the class manager.vehicles.VehicleType when it was attempting to create/load the class manager.administration.vehicles.VehicleTypeAdminBean.
I've encountered similar problems before. When the class loader attempts to load the class it looks at the import statements (and other class usage declarations) and then attempts to load those classes and so on until it reaches the bottom of the chain (ie java.lang.Object). If it cannot find one class along the chain (in your case it looks like it cannot load VehicleType) then it will state that it cannot load the class at the top of the chain (in your case VehicleTypeAdminBean).
Is the VehicleType class in a different jar? If you have a web module and and EJB module do you have the jar containing the VehicleType class in the appropriate place(s). Sometimes with web projects you have to put the jars in the WebContent/WEB-INF/lib folder or it won't find them.
Are both of these projects deployed separately (ie. two ears? or one ear and one war?) or are they together (ie, one ear with jars and a war inside?). I'm assuming the second given you declared your EJB local?
The jars that you are dependent on also have to be declared in your MANIFEST.MF files in the projects that use it.
I'm kind of running on guesses since I do not know your project structure. Showing that would help quite a bit. But I'd still check on where VehicleType is located with regards to your EJB class. You might find it isn't where you think it is come packaging or runtime.
Thanks #Chris for WebContent/WEB-INF/lib idea ! it works for me by following these steps :
1- Export my EJBs to a JAR (MyEJBs.jar)
2- I created another jar with your_installation_path/IBM/SDP/runtimes/your_version/binCreateEJBStrub.bat via CMD.exe, by executing this command :
createEJBStubs.bat <my_path>/MyEJBs.jar -newfile –quiet
3- A new jar will be automatically created in the same directory as MyEJBs.jar named MyEJBs_withStubs.jar
4- Put your new jar in WebContent/WEB-INF/lib
5- Call your EJBs by :
MyEJBRemote eJBRemote;
InitialContext ic = new InitialContext();
obj = ic.lookup("your_ejb_name_jndi");
eJBRemote = (MyEJBRemote ) PortableRemoteObject.narrow(obj,
MyEJBRemote.class);
eJBRemote = (MyEJBRemote ) obj;
Now you can call your EJBs from another EAR

Categories

Resources