-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Puzzle working w/ JarVisitor & .addAnnotatedClass() in JEE
PostPosted: Tue Oct 13, 2009 5:25 pm 
Newbie

Joined: Tue Oct 13, 2009 4:55 pm
Posts: 3
I am trying to programatically add a jar file (that is not on the class path) into code running on a jee app server, and to scan the entity for annotated classes, and then add the classes found to my Ejb3Configuration using .addAnnotatedClasses(myEntityClass).

It is almost working, but I've been stumped several days now, with some kind of class loading issue.

Here is my code:

//...unrelated code above
URLClassLoader loader = getURLClassLoader(jarPath);

/*
ClassLoader conextClassLoader = Thread.currentThread().getContextClassLoader();
URL entryURL = conextClassLoader.getResource(jarPath);
if (entryURL == null) {
throw new Exception("URL is null for jarPath: " + jarPath);
}
JarVisitor j = JarVisitorFactory.getVisitor(Thread.currentThread()
.getContextClassLoader().getResource(jarPath), filters);
*/
JarVisitor j = JarVisitorFactory.getVisitor(jarPath, filters);

Set<Entry>[] entries = (Set<Entry>[]) j.getMatchingEntries();
for (int i = 0; i < entries.length; i++) {
for (Entry c : entries[i]) {
try {
Class<?> entityClass = Class.forName(c.getName(), false, loader);
hibernateEjbConfiguration.addAnnotatedClass(entityClass);
} catch (Exception e) {
Logger.getLogger(DynamicPU.class.getName()).log(Level.SEVERE, null, e);
}
}
}

Iterator<PersistentClass> it = hibernateEjbConfiguration.getClassMappings();
if (!it.hasNext()) {
throw new Exception("No class mappings have been added to the Ejb3Configuration");
}

// ....unrelated code below


Here is what happens when I run it:
1) If I use the code (commented out above, but seems to be the way other are doing this) where the JarVisitor uses a URL derived from the current threads context classloader, the resulting URL is always null. My jarPath=/D:/EJB_Module_2.jar and I have also tried D:/EJB_Module_2.jar and //D:/EJB_Module_2.jar.
So I could never get that code to work.

2) But if I just use the code above (passing the JarVisitorFactory my jarPath (an absolute path) string ) the JarVisitor loads my jar and correctly identifies the annotated entity classes it contains. So far so good then.

3) The next step is to instantiate a class instances for each of these Entities and add them to my configuration in the line:
hibernateEjbConfiguration.addAnnotatedClass(entityClass);

=> I have found unless I build my own URLClassLoader and pass it to the method Class.forName(... , then I can not instantiate the class)
=> But when I call addAnnotatedClass(entityClass), while no exceptions or log warnings are generated, the resulting configuration has no mapped classes in it

One other bit of info: if I put this jar at jarPath in my classpath at deployment, everything works fine without any custom classloading. (By works fine I mean that I get an ejb3configuration that has the expected mappings of my entity classes in it).

And keep in mind this code is running on a JEE server (gfv2). Any insights/thoughts/advice are MUCH appreciated


Top
 Profile  
 
 Post subject: Re: Puzzle working w/ JarVisitor & .addAnnotatedClass() in JEE
PostPosted: Wed Oct 14, 2009 10:18 am 
Newbie

Joined: Tue Oct 13, 2009 4:55 pm
Posts: 3
One thing omitted above & some new findings, after you call

ejb3Conifguration.addAnnotatedClass(MyAnnotatedEntity.class)

you must then call

call ejb3Config.buildmappings()

or your configuration will not have mappings for your entities. Simple enough -in hindsight.

So at this point I have scanned my external jar using hibernate JarVisitor (passing it an absolute jar path) and identified my entity classes inside it.
In order to instantiated instances of those entity classes I created a custom URLClassLoader and used Class.forName(MyEntity, false, myURLClassLoader).

I add those classes to ejb3Configuration.addAnnoatedClass(), and call .buidMappings, and then examine the configuration and see all my entity class mappings are there.

However, the same basic issue remains, a few lines below the above code is:

ejb3Configuration.buildEntityManager()

and this throws this exception:
-----------
javax.persistence.PersistenceException: Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
at ejb_module1_session.DynamicPU.addPersistanceJar(DynamicPU.java:123)
at ejb_module1_session.EjbModule1SessionBean.persistEjbMoudle2Entity(EjbModule1SessionBean.java:79)
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.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1067)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:176)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2895)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3986)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:203)
at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:117)
at $Proxy59.persistEjbMoudle2Entity(Unknown Source)
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.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:154)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: org.hibernate.MappingException: entity class not found: Module2Entity2
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:170)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:667)
... 28 more
Caused by: java.lang.ClassNotFoundException: ejb_module2_entities.Module2Entity2

--------
To me this indicates I have managed to get the annotated class mappings into my configuration, but when I try to build the EntityManager, it is discovered that the working classloader has no access to the classes in the external jar.

I have found example code in a couple places that do not pass the JarVisitor an absoulte path, instead that code doies this:

JarVisitor j = JarVisitorFactory.getVisitor(Thread.currentThread().getContextClassLoader().getResource(jarPath), filters);

And in those examples, Class.forName(myEntity.class) is called without a custom URLClassLoader, which would indicate this approach somehow lets the working thread's class loader learn to load the class (Although in these code examples it is not specified weather or not the jar is in the class path or not)

But for me (running on gf2) that Thread.currentThread().getContextClassLoader().getResource(jarPath) only returns null.


Someone please help !!!


Top
 Profile  
 
 Post subject: Re: Puzzle working w/ JarVisitor & .addAnnotatedClass() in JEE
PostPosted: Wed Oct 14, 2009 11:42 am 
Newbie

Joined: Tue Oct 13, 2009 4:55 pm
Posts: 3
The solution I found is to set the working thread context classloader to my URLClassLoader, and also modify my URLClassLoadr to have the current context classloader as its parent.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.