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;
}
Related
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?
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.
I'm new to EJB. I have an ejb-jar file which contains, "Class1" and i deployed it to glassfish server. Now there is another jar file which contains only the following client file(it has a dependencey injection), so my problem is how should i execute this file?
I just deployed it to glassfish, but it doesn't work and show error in log file("it contains zero ejb").
import com.pack.Class1;
public class CreateAccoutnClient {
#EJB
private static Class1 class1;
public
static void main(String[] args) {
}
}
If anyone who have read EJB 3 in Action, i'm tring to deploy chapter3 code to glassfish with eclipse.
Thanks :)
EJB context doesn't execute any main methods, with Glassfish (and others) you must deploy a war to have entry points that run your app or methods (web services or web app).
A jar can contain MDB, remote ejbs or scheduled timers, or could be just a library. The only way to execute some initialization method at startup is to use the EJB3 #Startup annotation
I have an EJB with some JPA logic that I use in my java EE projects.
Instead of copying the class in every project I'm trying to put it in a separate jar, so I have this structure:
Java EE project with EJB and WAR projects in it
JPALogic: JAR project with JPALogic class in it
RemoteServices: JAR project with beans interfaces
Services: EJB project with beans, including JPALogic and RemoteServices as libraries
Frontend: WAR project with frontend, including RemoteServices as library.
JPALogic is used only in the EJB project and there's no reference to it in other parts of the Java EE app. In JPALogic library I've my JPALogic bean:
#Stateless
#LocalBean
public class JPALogic {
#Resource
private EJBContext ejbContext;
#Inject #ShardedPersistenceContext
private EntityManager em;
public JPALogic() {
}
[...lots of methods...]
}
It works perfect if JPALogic code is directly in the EJB project, but when I put it in the external library deployment become very unstable (netbeans 8 + glassfish 4) and almost every deploy fail with this error:
Exception while deploying the app [app] : Cannot resolve reference [Remote ejb-ref name=com.my.autenticacion.services.AutRolBackendServices/jpa,Remote 3.x interface =com.my.infraestructura.jpa.JPALogic,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session] because there are [2] ejbs in the application with interface com.my.infraestructura.jpa.JPALogic.
I've search but it seems this kind of error appear when an interface have more than one implementation, and this is not the case: there's only one bean named "JPALogic" and, inspecting the ear, JPALogic.jar appear one time only.
I'm doing something wrong?
If you jar contains EJB annotations (#Singleton, #Stateless, #Stateful component-defining annotations), its not a simple jar, but an ejb-jar, and should be packaged as a module.
Solution:
You should reference the JPALogic.jar in application.xml as an EJB module.
You can also add a "Class-Path: JPALogic.jar" in the META-INF/MANIFEST.MF of the referencing modules to garantee visibility. It could be visibile, depending on the container.
Like this:
application.EAR
META-INF/application.xml
(must have a reference to the JPALogic.jar EJB module)
JPALogic.jar (EJB-JAR)
remoteservices.jar
services.jar
META-INF/MANITESF.MF Class-Path: JPALogic.jar
remoteservices.jar
frontend.war
For a more details, refer to the JAVA EE 6 specification, chapter EE.8:
EE.8.3.2 EJB Container Class Loading Requirements
EE.8.5.2 Deploying a Java EE Application
I am trying to use Arquillian to test my JPA repository classes. However I only get nullpointer exception telling me that it doesn't find the persistence.xml. How do you configure it in a standard Maven project?
Have you looked # the official documentation here. The project structure suggests that its built using Maven.
If you still run into issues do post the exception messages.
Good luck!
It looks like your ShrinkWrap deployment does not contain the persistence.xml in the right path. The persistence.xml file should be located in the META-INF directory of a JAR, or in WEB-INF/META-INF directory of a WAR. You could verify this in two ways:
Through the verbosity flag of the Archive.toString(...) method:
In your #Deployment method, you can print out the contents of the archive, using the toString method, like
#Deployment
public static Archive<?> createDeployment() {
WebArchive war = ShrinkWrap.create(WebArchive.class).addClasses(Foo.class);
System.out.println(war.toString(true));
return war;
}
Configuring Arquillian to write the generated deployment to disk:
You can add the engine configuration element to your arquillian.xml with the deploymentdeploymentExportPath property, like
<engine>
<property name="deploymentExportPath">target/deployment</property>
</engine>
This would instruct Arquillian to write the deployments it generates into a subdirectory under the target directory generated by Maven.
There is also bunch of examples in the showcase project on github, including JPA testing (also using Arquillian Persistence Extension).
Hopefully this will lead to you to the right path :)