It's been a while since I started this project, and I had switched to using webservices because they were so easy to implement and they worked rather well with the NetBeans RCP application. However, as I'm sure you know, there are some limitations to what you can do with webservices, and I have started to try to replace them with EJBs. As I'm sure you're also aware, calling remote EJBs from Netbeans platform apps is a real pain, and I notice that you have done just that.
I've built and deployed the ejb's on my glassfish server (4.1), and I can access them and retrieve data from stand-alone, command line apps with no problem. I've become very proficient at bundling the correct libraries and putting it all together in a netbeans platform application. I have no problem getting an initial context, and querying the context for all of the available jndi entries. However, when I try to do a look-up on any of those jndi entries, I get a naming exception, even though I got the jndi name directly from the server. I have tried with both portable and non-portable names created by the glassfish server. Nothing works. I have the glassfish libraries and the ejb libraries all packaged into one netbeans module. When I attempt the lookup, there are no errors on the server side, and only the naming exception in the netbeans client.
There are many stories on the web from people who have exactly the same problem, but there doesn't seem to be a solution other than switching to JBoss or WebSphere or some other costly solution. I have even tried the Payara (Glassfish) server to no avail.
If you do indeed, have this puzzle figured out, I would love to hear what you do did to accomplish this herculean feat! Please do share. I'll provide any information you need as to what I've done to get to this point, and hopefully you can provide the missing piece to get me to the promised land.
Boris Heithecker wrote:
> Hello,yes, it's possible to use jms and remote ejb calls in a NetBeans RCP, an application has been running in a production environment for over a year now.Â
> In my experience, the only viable solution is adding glassfish-embedded-all as a library jar plus some adaption to the netbeans platform. The all-in-one distribution (glassfish-embedded-all-4.1.jar) is only one jar and 87MB, not 400, and you'll hardly get a smaller solution if you assemble a working jms message queue from scratch.Â
> Other solutions could be 1. launching an external glassfish installation in embedded mode - not possible because of netbeans classloader issues, 2. lauching an external gf installation as an osgi bundle from within nb - not possible because apache felix doesn't comply with the nb classloader system here, too.Â
> I've added glassfish-embedded-all-4.1.jarÂ to a regular moduleÂ as an additional wrapped jar (Project Properties -> Libraries -> Wrapped JARs tab) and exported only the official java ee API packages (Project Properties -> API Versioning). This leverages part of the Java EE APi to NB. On platform startup, a tiny glassfish domain (domain directory plus domain.xml with all unnecessary services removed) contained in the module sources under ModuleProjectDir/release is launched - using a custom adapted glassfish runtime builder for configuration of the running gf instance.Â
> To use jms, you have to add jms resources to the domain.xml, but it works even in rather poor network conditions.Â
> It's impossible to go into more detail at this place, because, after all, using java ee apis on top of the platform is an accumulation of many small solutions which can't be given here at full length. But our approach is definitely a viable solution, it's even possible to secure ejb remote calls and jms connections.Â
> For part of my remote database communication, secured webservices are used as well, but I've found out that these are definitely slower and could become a serious performance issue if you need quick responses to user activity.Â
> Hope this could help you,
> 2015-11-12 15:10 GMT+01:00 kpenrose <address-removed (address-removed)>:
> > I have just started programming on the NetBeans RCP, using maven, trying to port some existing JavaFX applications into the platform.Â The JavaFX applications are part of a suite of apps, so I thought it would be cool to allow them all to be modules which could be loaded into the platform as needed by each group of users.
> > The JavaFX apps rely heavily on JMS and of course database access.Â Both of these led to huge problems for me on the RCP.Â I found that adding the necessary jar files for remote EJB lookup to be very painful, so I switched to webservices (which is very easily done by adding the @WebService annotation to the beans - no need for Remote classes, etc.)Â Integrating webservices into the RCP was relatively painless.
> > However, adding JMS has been another story - and it's still related to adding the necessary jar files to the project to allow the stand-alone application to access services housed in the glassfish 4.1 server.Â I've tried adding gf-client.jar and imqjmsra.jar from the org.glassfish.main branch of the repositories.Â I tried creating two wrapper modules, one for each, and using them in the RCP application.
> > In each module that uses classes from these wrappers, I added a provided dependency, based on the fact that I read that doing so keeps that wrapper module from being added to the current module.Â I obviously need the reference to the wrapper module in order to compile my code.Â After following this procedure, I get many ClassNotFound errors when trying to run the application. Adding them as compile dependencies removed the ClassNotFound errors, but then I get issues of the app trying to load a class from two different modules.
> > For anyone familiar with using gf-client.jar, you also need all of the module jars that are found in the $GLASSFISH_HOME/modules directory to be on the classpath.Â Not sure how to wrap up this mess either.Â I found a way around those problems by wrapping the glassfish-embedded-all.jar file, which contains everything needed, but again, compile dependencies in each moduleÂ and I end up with a 400MB application.Â Using this method is the only way I have been able to get webservices working AND JMS.
> > So, my question really boils down to: how do you wrap a jar of jars (hundreds) and make them available to all requiring modules in an application?Â Something that seems simple on its cover is turning out to be a nightmare for me.
> > Thanks.
a NamingException is mostly only a wrapper for some other exception that happened during the look-up. So, can you provide any stack trace? Also, please show the lines of code where you create the initial context and then look up the remote bean.
One problem is that glassfish/payara is not fully compliant with the NetBeans classloader system. When a remote bean is being looked up for the first time, the iiop infrastructure creates an implementation stub of the remote interface at runtime, i.e. it generates java bytecode (using a library called Primitive Function Library). The new class is defined on the invoking thread's context classloader (using java reflection API), which in NetBeans is the so called system classloader. The problem is that this "system classloader" is a purely delegating classloader. It delegates all calls to one of its multiple parents, which are the module classloaders. Because of this, while it is possible to define an implementation class at runtime on the system classloader, this classloader will never find them afterwards. This causes an exception, which is then possibly wrapped into a NamingException. My workaround is to simply replace the context classloader only during the look-up with a classloader which itself has the system classloader as its parent.
I've uploaded a part of my own implementation to github (https://github.com/borisheith
Also, for a start, don't run the server on the same physical machine as the NetBeans client. This would need a little bit more configuration and will fail otherwise.
Which libraries do you bundle? payara-embedded-all (all glassfish in one jar, from Maven) plus the jar containing your beans should do.
Futher, you have to use the jndi names starting with "java:global/....". These names are available from the server log file after deployment.
2017-05-12 16:12 GMT+02:00 kpenrose <[hidden email]>:
Dr. Boris Heithecker
Lüneburger Str. 30
Tel.: 0 42 05/ 31 58 34
|Free forum by Nabble||Edit this page|