How can I deploy JPA 2 applications on JBoss SOA 5.x? - java

I am working on migrating an application originally written using EJB3 persistence (JPA 1.0) on JBoss SOA server version 5.2 so that it uses type safe queries and criteria queries from JPA 2.0 (Hibernate Implementation). So far, I have been completely unable to get the EAR to deploy because it cannot find the proper version of the javax.persistence libraries. The error shows that it cannot find the class javax.persistence.criteria.Expression. From what I can see it is loading the javax.persistence classes from the ejb3-persistence library which is built into JBoss. I have tried various methods which are supposed to cause JBoss to use the application libraries first, but to no avail. Any help would be appreciated.
Methods I have tried:
Adding a "<loader-repository>" configuration to the jboss-app.xml file
Adding a jboss-classloading.xml file to the EAR's META-INF folder
Modifying the ear-deployer-jboss-beans.xml file to use isolated classes.

The answer is that the "jboss-classloading.xml" file will work for web application, but there is no way to override the classloading for EJBs which are published. The libraries for published EJBs have to be unique at the server level and since JBoss aleady includes a library which handles the java.persistence.* namespace, you cannot use any other versions of JPA in EJBs.

Related

Java EE Specification vs Implementation

I have recently started on Java EE and having a tough time understanding it. I have read some answers here on SO but I still feel like there are some gaps in my understading. Basically, Java EE is a specification and application servers like TOMCAT, Glassfish etc., have the concrete implementations. Also, anyone can provide implementation for EE.
So, I have downloaded javax.sevlet-api-4.0.1-sources.jar from Maven repo and I can see that they are just Interfaces and I assume we just use them to build the project?
In tomcat lib folder there is a servlet-api.jar. is this the tomcat implementation of Servlet? and if it is, then is it possible to replace it with another servlet version implementation?
Now, Hibernate is the implementation of Persistence API. if i want to use Hibernate with Tomcat. I just need to add the Hibernate related jars to my application and can use them for both build and run? without actually getting the contract classes.
You need the servlet-api jar file when compiling your code, because that's where e.g. HttpServletRequest is. You don't need to include that jar with your application, because it is provided already by the Servlet Container you deploy your war file to, e.g. Tomcat.
With Tomcat, the implementation of the various servlet classes are in catalina.jar, at least for Tomcat 9, e.g. ApplicationHttpRequest is the class implementing HttpServletRequest. You don't need this to compile your code.
To be accurate, Tomcat is not a fully fledged JavaEE container, it only handles part of the JavaEE spec (mainly servlet, jsp, jndi and a few others).
And as Andreas wrote you need serlvet-api.jar to compile your code (otherwise HttpSerlvetRequest will miss), but as tomcat already provides it (as an interface) as well as an actual implementation, you should add it as a "provided" dependency in your maven file.

Legacy Spring 2.5.6 Migration to Spring 3.x or 4.x in WLS & Java 8

Upon being handed a legacy Spring 2.5.6 application (deployed in WLS 12.1, java 7), I've been asked to migrate it to WLS 12.2 and java 8. I am attempting to re-build the application with a source and target of "1.8". It builds OK, but on deployment/test, I immediately, I have an issue where Spring 2.5.6 cannot seem to find application context files on the classpath in this new environment:
org.springframework.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathPatchingResourcePatternResolver.java:346)
| Resolved location pattern [classpath*:context*.xml] to resources[]
No resources are found. In fact, no classpath directory trees are even searched. I've checked to make sure the files are present and the classpath looks right in the WLS log files. All of this works great in java 7/WLS 12.1 but fails in java 8/WLS 12.2.
My guess is that Spring 2.5.6 is so ancient that it may not be working correctly in a java 8 environment. Any recommendations on how to easily migrate to Spring 3.x or 4.x w/out making any (if possible) source code changes?
Pieces of Spring 2.5.6 being used:
SpringBeanAutoWiringInterceptor (overrides getBeanFactory() to use
ClassPathXmlApplicationContext)
Spring JDBC's SimpleJdbcDaoSupport
Spring Transaction annotation (#Transactional)
That's about it. Not a whole lot of Spring but enough to warrant the question: which Spring version would be the easiest to migrate to without making any (or many) source code changes? Or is there a better way to handle this?
I got this to work by upgrading to Spring 4.1.9, which contains the same classes as Spring 2.5.6 (although many of them are deprecated).
One note, however. When making this change I had an issue with Spring 4 no longer finding/loading the context files from the CLASSPATH when using an exploded directory on the filesystem.
The issue was resolved here:
ClassLoader.getResources returning an empty Enumeration on a Weblogic/Spring application

How to superseed Glassfish's built-in libraries with dependencies shipped in EAR?

GlassFish 4.1 provides EclipseLink 2.5.x in glassfish/modules. I want to use 2.6.4 in my application and am including it when packaging it with maven-ear-plugin:2.10.1 with
<configuration>
<finalName>linuxtracker2</finalName>
<version>7</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
and the EJB and WAR module as dependency (and default values otherwise). The application deploys and works fine, but I suspect that EclipseLink 2.5 has an issue and I want to overwrite it anyway because I don't want to (double) configure the server to provide dependencies.
I figured out so far that GlassFish has a classloader hierarchy and that load requests are delegated to the topmost parent which can satisfy it, but the docs fail of course to explain how to use that. There's Circumventing Class Loader Isolation which I'd say from my understanding does the opposite of what I want to acchieve (isolate the class loader to use my packaged dependencies).
My application setup is the standard: entity classes and EJB interfaces, EJB implemetations, web frontend and EAR maven module.
Related troubles:
Glassfish 4 documentation is hard to find via google, search terms with "glassfish 4" return results for 3.x only, I didn't manage
the Oracle documentation database http://docs.oracle.com doesn't provide documentation for GlassFish 4.x - that's low, even for Oracle
links in the 3.x documentation - why not try it since I have unlimited time - include dead links like http://blogs.sun.com/sivakumart/entry/classloaders_in_glassfish_an_attempt on http://docs.oracle.com/cd/E19226-01/820-7695/gatej/index.html
WildFly has a quite cryptic feedback which is only targeting core developer judging from its form and the possility to understand it (see https://stackoverflow.com/questions/43090661/how-to-figure-out-what-missing-service-dependencies-in-wildfly-10-mean for example); afaik it's the only other FLOSS Java EE application server which is Java EE 7 certified
I can't user GlassFish 4.1.1 because of https://java.net/jira/browse/GLASSFISH-21437.
GlassFish is no longer supported by Oracle, and therefore just an open source project now. The documentation can be found at https://glassfish.java.net/documentation.html - you will need to download the "Administration Guide" PDF, though the others are quite useful too.
What you're trying to do here isn't possible in GlassFish, but is a feature added to Payara Server, which is derived from GlassFish (disclaimer: I work for them).
For EAR files, Payara Server has added the option to add <classloading-delegate>false</classloading-delegate> in your META-INF/glassfish-application.xml file. This should stop your application using libraries from Payara Server when you have your own versions packaged in your EAR.
For your specific use-case, though, you would not need to use this since Payara Server already comes with EclipseLink 2.6.4 in the latest build, 171.1

How to depend on two different versions of a library?

I am using ElasticSearch and JackRabbit (or...I am trying too). JackRabbit seems to be depending on Lucene 3.6.x and ElasticSearch is depending on 4.3.1. I am using Maven and JBoss 7.1.1. I get Lucene 4.3.1 on the classpath but then h*** is breaking loose in the log because JackRabbit requires something from the older Lucene.
How do I solve this?
you will need to take the conflicting libraries that you wish to use (elastic search and jackrabbit) and make both into jboss as7 modules. with jboss 7 modular classloading you can "contain" each of them with its own dependencies as a separate module and expose to your application only the api that you use.
its a bit complicated (full docs here) but will allow you to have each of them use their own version of lucene - they will each be packed into a module with all of theor dependency tree.
EDIT - there's some more info on how to export only some of a module's content in te jboss modules documentation. you want to make sure you dont export lucene out of any of the modules
You can create two custom classloaders instances and load ElasticSearch class with one of them and JackRabbit with the other. The first one must be loading classes from Lucene 3.6.x jar, the other from v.4.3.1 jar

Tomcat: how is working the shared lib directory?

I made search on subject, but didn't find anything easy to understand...
We have a tomcat (v5.5). There is many webapp deployed on it. Each webapp has all librairies in the WEB-INF/lib directory. So there is a lot of duplication.
A classic library (XXX_API) was created in order to organize some common methods. So this librairy is added in each webapp to compile but not deployed with them. This librairy is deployed in shared directory of Tomcat.
We tried to integrate some DAO using JdbcTemplate of Spring 3.1.1 in the common librairy.
So we had to deploy Spring librairies in shared directory in order to deploy our XXX_API.
Now, we can't launch all applications.
Some of them crashed with these exception : java.lang.IllegalArgumentException. Class org.springframework.jdbc.config.JdbcNamespaceHandler does not implement the NamespaceHandler interface.
For information, they are developped with Spring 2.0.6 :(
The problem seems to be localized in the applicationContext.xml.
So, here my questions :
how is working the shared directory of Tomcat ?
Is it loaded in priority compared to the lib directory of the web app ?
Is just a pb about namespace declared in applicationContext.xml ?
Is it possible to have both spring versions ?
Thank you.
What you are really asking is how the classloaders load, in what sequence, etc. This page explains all of the classloaders that are involved in a webapp's execution inside of the tomcat container quite well. It tells where they look for classes, in what sequence, and which classes can be seen by each webapp as well as the container itself. Note, changes to this are significant across tomcat versions.
http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html
The main use that i've seen for the shared lib folder is for things like jdbc drivers, jta transaction managers and other infrastructure like things that:
The container needs to have available (in the case of jdbc and jta, to create jndi datasources and the jta user transaction)
Are environment specific, like the jdbc driver, when you are going to use the OCI version of the oracle driver. In this case, you have to match the ojdbc.jar file with the version of the native oracle client library installed on that machine. Another example would be jms connectors.
Anything that uses native libraries, as loading that jar multiple times would cause issues when it tried to load the native library a second time.
I wouldn't go putting actual app libraries like spring in the shared lib folder.
Probably because one class is loaded by app classloader, another by shared classloader.
Save yourself the trouble, don't use shared directory. What for? To save some disk space?
So, i have deleted all spring jars in each web application. I imported the spring lib (3.1.1) present in shared directory. And i unchecked them (under netbeans) to not have them in the build.
I even changed the declaration in web.xml, applicationContext.xml and Spring Servlet in order to be standardized with servlet v2.5.
All seems to be fine now...

Categories

Resources