Skip to main content

[Glassfish embedded] Problem with JPA2 entities in jar in a war

10 replies [Last post]
andersaab
Offline
Joined: 2009-12-22

Hi everybody
We have used Glassfish Embedded for unittesting a project for a while now without any problems. The project is a single war with both EJB's and JPA2 entities.

Now we are trying to split up the application in different projects. We have put all the JPA2 entities together with persistence.xml in a separate maven jar project,
and the parent war project has a dependency to the jpa project. This works fine when deployed to Glassfish, but the TestNG tests using Glassfish Embedded stopped
working. No matter what we try, the persistence.xml doesn't seem to get loaded. This is the root exception we get:

...
Caused by: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName evotePU
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.init(EntityManagerWrapper.java:121)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:141)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:134)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:252)
at no.evote.service.impl.BaseServiceImpl.create(BaseServiceImpl.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5243)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:615)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:567)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:157)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:139)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:858)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:367)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5215)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5203)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:190)
... 32 more

We are using glassfish-embedded-all version 3.0, and the EJB embeddable API. This is how we start Glassfish:

@BeforeSuite
public void setUp() {
Map properties = new HashMap();
properties.put(EJBContainer.MODULES, new File("target/classes"));
properties.put("org.glassfish.ejb.embedded.glassfish.instance.root", "./src/test/glassfish");
container = EJBContainer.createEJBContainer(properties);
context = container.getContext();
}

This is in the war project, so target/classes refers to this project (with ejb's and controllers) and not the JPA2 project. I tried changing this to the JPA2 project, but it made no
difference.

Does anyone have any suggestions as to why this doesn't work? Having JPA2 entities in a jar as part of a war should work, right? All help appreciated!

Regards, Anders

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
stlecho
Offline
Joined: 2003-06-12

> This works:
>
> File[] ejbModules = new File[2];
> ejbModules[0] = new
> ew File("target/simple-0.1-SNAPSHOT-LOCAL.war");
> properties.put(EJBContainer.MODULES, ejbModules);
>

In my project, I'm using "[i]properties.put(EJBContainer.MODULES, new File("target/MyEntities-0.0.1-snapshot.jar"));[/i]", but this results in the following warning: "org.glassfish.deployment.common.GenericAnnotationDetector scanArchive
WARNING: Failed to scan archive for annotations26".
The referenced JAR file exists in the classpath, but Glassfish has problems in finding it. That's what I suppose, because the warning message does not give enough details.

Could you verify that when you use the JAR that contains the jpa2 entities and not the WAR that contains this JAR, the system continues to work correctly ?

Regards, Stefan Lecho.

mvatkina
Offline
Joined: 2005-04-04

EJBContainer.MODULES denotes an EJB module, and JPA entities do not constitute an EJB module.

stlecho
Offline
Joined: 2003-06-12

> EJBContainer.MODULES denotes an EJB module, and JPA
> entities do not constitute an EJB module.

In a previous answer, I read "[i]and the jpa2 entities are loaded from a jar inside simple-0.1-SNAPSHOT-LOCAL.war[/i]". If I understand you correctly, this would mean that the WAR contains more than just the JPA2 entities but also for instance an EJB module. Could this be confirmed ?

How can I configure Glassfish such that in my unit tests, the JPA2 entities are loaded from the provided JAR ?

mvatkina
Offline
Joined: 2005-04-04

Testing a war file is a bit different. Otherwise (post GlassFish 3.0) all entries in the classpath (besides GlassFish jars) will be part of the deployed artifacts (either as EJB modules or as libraries). If you want to exclude something from deployment, you need to remove those entries from the classpath.

hwellmann
Offline
Joined: 2008-08-16

Using

properties.put(EJBContainer.MODULES, new File("target/classes"));

Embedded Glassfish only sees the classes and resources from your current project, not from your JPA project.

I don't know if Embedded Glassfish supports a classpath composed of multiple folders. For my JUnit tests, I build a WAR and deploy it to Embedded Glassfish.

HTH,

Harald

andersaab
Offline
Joined: 2009-12-22

Hi
I was thinking the same thing. I tried with different variants but always get the same result, even if I remove the EJBContainer.MODULES property.

How do you deploy the WAR in your tests? Are you using Arquillian or are you using the Glassfish Embedded API?

Regards,

Anders

andersaab
Offline
Joined: 2009-12-22

Ok I just had a minor breakthrough....

This works:

File[] ejbModules = new File[2];
ejbModules[0] = new File("target/simple-0.1-SNAPSHOT-LOCAL.war");
properties.put(EJBContainer.MODULES, ejbModules);

So if feed the webapp compiled by Maven to Glassfish, everything is fine and the jpa2 entities are loaded from a jar inside simple-0.1-SNAPSHOT-LOCAL.war. So unit tests executed with maven works. But the downside is that we now can't execute tests in Eclipse using the Eclipse compiled code (edit, compile, run) but need to do a maven build each time we change code.

But, shouldn't this work in Embedded Glassfish?

File[] ejbModules = new File[2];
ejbModules[0] = new File("../simple-jpa/target/classes");
ejbModules[1] = new File("target/classes");
properties.put(EJBContainer.MODULES, ejbModules);

Meaning, use target/classes for both this project and the jpa project? Would be very nice to get this working.

-Anders

hwellmann
Offline
Joined: 2008-08-16

Yes, that's more or less what I'm doing, only I'm using the native API org.glassfish.api.embedded.*, as I could not find any usable documentation for the javax.ejb.embeddable.EJBContainer API.

I agree that a classpath composed from multiple directories [i]should[/i] work, but I believe it does not.

I work with m2eclipse, so it's not a big deal running a Maven build before running (or debugging) my integration tests in Eclipse interactively. Surely you do not want to run all your integration tests automatically when saving a source file in Eclipse?

Regards,
Harald

andersaab
Offline
Joined: 2009-12-22

No that would be madness :)

But we use Glassfish Embedded for unit testing, so in order to do some kind of TDD it must be possible to do a quick compile and test. Our maven build takes about 40 seconds so that is a bit too much for this process.

It would be nice to get a confirmation from someone that multiple directory classpath won't work. That's what I observe but maybe it should be done in a different way.

I am also trying this in 3.1 builds, but currently I get stopped by another issue:

WARNING: C:\Dev\workspace-admin\simple\gfembed6064864137021454253tmp\config\logging.properties not found, creating new file from template.
org.jvnet.hk2.component.ComponentException: problem initializing
at com.sun.hk2.component.SingletonInhabitant.get(SingletonInhabitant.java:71)
at com.sun.hk2.component.EventPublishingInhabitant.get(EventPublishingInhabitant.java:136)
at com.sun.hk2.component.AbstractInhabitantImpl.get(AbstractInhabitantImpl.java:61)
at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:215)
at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:131)
at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:466)
at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:326)
at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:308)
at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:301)
at com.sun.enterprise.glassfish.bootstrap.ASEmbedded.start(ASEmbedded.java:97)
at org.glassfish.api.embedded.Server.(Server.java:317)

I have tried putting logging.properties everywhere but haven't managed to get GF beyond this point.

Thanks for helping Harald!

-Anders

ljnelson
Offline
Joined: 2003-08-04

I don't have time to dig through the forum messages right now, but embedded testing in Glassfish has always been problematic. Go ahead and do a search on my username (ljnelson) and embedded Glassfish and you'll dig up some old posts on the subject. I filed a bug at one point which I [i]believe[/i] was fixed about how everything needed to be in one classpath directory.

Finally, apparently the fact that it's even possible to run the embedded container standalone without a full-fledged Glassfish installation behind it--why else would I want to run such a thing? oh well--was apparently unsupported. I don't know if that ever changed or not. I seem to recall a lot of manual tweaking of the domain.xml file early on as well.

One of the reasons I am so excited about the rise of Arquillian (http://community.jboss.org/docs/DOC-14376) is that it will force this embedded container to get better.

Best,
Laird