web stats
NoSuchMethodError using JPA - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 07-19-2016, 12:48 AM
rafraider rafraider is offline
Mirth Newb
 
Join Date: Jul 2016
Posts: 6
rafraider is on a distinguished road
Default NoSuchMethodError using JPA

Mirth Connect 3.4.1
Windows Server 2008 R2
Java 1.8_92

Hi,

i have written a java library that is creating a PDF. It's a dump of all data of a patient in our database.
In that library i'm using the eclipselink java persistence api (JPA).

I created a new resource containing my library and all dependent libraries:
commons-lang3-3.4
eclipselink
itextpdf-5.5.9
javax.persistence_2.1.1.v201509150925
jcifs-1.3.18
mysql-connector-java-5.1.23-bin
org.eclipse.persistence.jpars_2.6.3.v20160428-59c81c5

The very first time i try to create a query, a NoSuchMethodError is thrown by the entity manager.

The mysterious thing is:
I testet the instance of the variable with reflection. The instance of the variable is definitely a org.eclipse.persistence.internal.jpa.EntityManager Impl

I can run the process on my local pc or even on the server via command line and there is no problem. There is a main method creating some test documents.

I know that Rhino is using a class loader, but maybe there's a problem with using interfaces?
The variable is an interface javax.persistence.EntityManager and the instance is the EntityMangerImpl. When i try to call the method of the interface Rhino can not find the method of the implementation instance?

Or is there maybe a conflict with the persistence library which Mirth Connect is using?

The exception:
Code:
[2016-07-15 12:18:22,250]  ERROR (com.mirth.connect.connectors.js.JavaScriptDispatcher:193): Error evaluating JavaScript Writer (JavaScript Writer "..." on channel ...).
java.lang.NoSuchMethodError: javax.persistence.EntityManager.createNamedQuery(Ljava/lang/String;Ljava/lang/Class;)Ljavax/persistence/TypedQuery;
	at ....getPatient(....java:50)
	at ....createDocument(....java:680)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
	at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
	at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:1479)
	at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:815)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:109)
	at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:393)
	at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3280)
	at org.mozilla.javascript.InterpretedFunction.exec(InterpretedFunction.java:120)
	at com.mirth.connect.server.util.javascript.JavaScriptTask.executeScript(JavaScriptTask.java:142)
	at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.doCall(JavaScriptDispatcher.java:149)
	at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.doCall(JavaScriptDispatcher.java:122)
	at com.mirth.connect.server.util.javascript.JavaScriptTask.call(JavaScriptTask.java:113)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

Last edited by rafraider; 07-19-2016 at 04:42 AM.
Reply With Quote
  #2  
Old 07-19-2016, 05:16 AM
rafraider rafraider is offline
Mirth Newb
 
Join Date: Jul 2016
Posts: 6
rafraider is on a distinguished road
Default

ok, i tried a dirty trick with a cast.

Code:
EntityManagerImpl emImpl = (EntityManagerImpl) em;
TypedQuery<Patient> query = emImpl.createNamedQuery(...);
but that is no solution. it couples me to the EntityManagerImpl class.

It seems like the EntityManager interface which comes with my dependent libraries is not used in the context of my channel. Instead the EntityManager interface, which is loaded by the server (persistence-api-1.0.jar) is used and the methods are not declared.

Does anyone know how to force Mirth Connect using the persistence library i loaded in the resources?

Last edited by rafraider; 07-19-2016 at 05:24 AM.
Reply With Quote
  #3  
Old 07-19-2016, 07:38 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,116
narupley is on a distinguished road
Default

The classloader used in Rhino contexts is built up using the parent (overall server classloader), and any custom resource libraries you're using. According to ClassLoader documentation, classes will first be searched for in the parent. Since your custom libraries include a class that is also on the overall server classpath, it makes sense that the JVM is not choosing your class by default.

We did add a way to do this though. In JavaScript you can call ContextFactory.getIsolatedClassLoader() to get a ClassLoader that only includes the resources you have set on that specific connector, and does not include the overall server classloader as a parent. With that you can call loadClass directly. You can create instances with newInstance or by getting the Constructor first. Commons Lang also includes a ConstructorUtils class.
__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead?

Nicholas Rupley
Work: 949-237-6069
Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first.


- How do I foo?
- You just bar.
Reply With Quote
  #4  
Old 07-21-2016, 01:32 AM
rafraider rafraider is offline
Mirth Newb
 
Join Date: Jul 2016
Posts: 6
rafraider is on a distinguished road
Default

Quote:
Originally Posted by narupley View Post
We did add a way to do this though. In JavaScript you can call ContextFactory.getIsolatedClassLoader() to get a ClassLoader that only includes the resources you have set on that specific connector, and does not include the overall server classloader as a parent. With that you can call loadClass directly. You can create instances with newInstance or by getting the Constructor first. Commons Lang also includes a ConstructorUtils class.
It woul be nice, if i could use it, but the code of the JavaScript part looks like this:

Code:
var internalId = parseInt($("internalId"));
var documentCreator = new Packages.mypackage.DocumentCreator(internalId);

try {
    documentCreator.createDocument();
} catch (err) {
    handleError()
}
There are many obstacles with that kind of class loading policy.
  1. when writing own class libraries you have to know all the hundreds of libraries the mirth connect server is using.
  2. you have to load every conflicting class with isolated class loader
  3. you have to write the process of your use cases in the javascript part
  4. need a lot of programming skills
  5. maintanance is hard

My suggestions:
  1. the first classloader should be the isolated class loader. In this case writing independent libraries would be easy.
  2. maybe add an option to channels or to destination connectors, which allows to configure which class loader should be used

i wanted the JavaScript code to be as little as possible. The whole process is done in Java. I can't load the class in Java via isolatedClassLoader.
the library i have writen is already compiled using the javax.persistence.EntityManager interface.

Is it possible to overload the global loaded EntityManager interface of mirth connect in the javascript code?

Last edited by rafraider; 07-22-2016 at 12:23 AM.
Reply With Quote
  #5  
Old 07-22-2016, 04:08 AM
rafraider rafraider is offline
Mirth Newb
 
Join Date: Jul 2016
Posts: 6
rafraider is on a distinguished road
Default right way

I found a comment from Hugo Soares in MIRTH-3835 and fully agree with his opinion. The classloading priority would solve my problems.

The next comment from Nick Rupley (maybe you?!?) pointed out, that

Quote:
Classloader priorities is an interesting idea; we'll consider that in the future. In the meantime though this should be sufficient to satisfy fringe cases where you need to load/instantiate a class from a specific library and not from the overall server classpath.
But i could not find any issue for that. Do you know when to expect it?
Reply With Quote
  #6  
Old 06-25-2019, 06:13 AM
agermano agermano is offline
Mirth Guru
 
Join Date: Apr 2017
Location: Indiana, USA
Posts: 849
agermano is on a distinguished road
Default

Still not on the roadmap.

http://www.mirthcorp.com/community/i...wse/MIRTH-4198
Reply With Quote
Reply

Tags
classloader, jpa, library, rhino

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 02:23 AM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Mirth Corporation