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
Related
I'm currently working on an ebanking platform, so out customers are banks. To extend this platform, we develop our own 'xDK' (development kit) for 3rd party developers (usually the banks themselves).
When xDK is used as a dependency (via maven or gradle), it brings along a lot of transitive dependencies in order to work (~25MB). I was trying to think of solutions to make the dependency a bit lighter to use (given that it needs all of its dependencies) which in turn will promote having smaller, more focused services (not exactly micro-services but at least a step closer).
The current situation's benefit is that every service/project can use its own version of xDK and it doesn't have to update until it needs to. The problem is that it doesn't scale. If we assume 100 WAR files having xDK as a dependency, we create a 2.5GB overhead on the application server (even if they all use the same version).
I'll list two options I was thinking of, but I'd like to know if there are better solutions for this problem. Feel free to ask for more info. Thanks in advance.
Similar to JavaEE components (JPA, JAX-RS, ...), we'll have an 'api' dependency and the implementation. The projects will only declare the 'api' as a provided dependency while the implementation will be provided like so:
JBoss module
I haven't worked with other application servers. We (and our customers) only use JBoss EAP, so this might be a JBoss specific solution. We can create a JBoss module for xDK and then make every deployment depend on it via the JBoss deployment descriptor. The benefit is that we get rid of the multiple copies of the library, but we lose on version flexibility. This would mean that there needs to be some kind of governance on which version of xDK you code against in your service. Also, every time there is a breaking change, we'd need to update all services if we want to update the JBoss module to the latest version.
Bundle in an EAR
EARs allow multiple WAR files in them and also jars as libs. xDK will be an EAR dependency. Again, we have the same pros and cons as the previous solution. This solution is JBoss independent. However, it needs an extra build step to collect all the projects and bundle them, which might be annoying for out customers if they need to bundle their own services.
How about using the maven dependency scope of provided to declare that for the individual war files the jar file is provided outside of the war file, and then have another mechanism to inject the shared jar file into the application server?
c.f. https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
I have a Tomcat 6 server which is hosting a portlet container (in a war) and several portlets (each one packaged in its own war). We have a requirement to share data between these portlets, and due to the version of the portlet container we are using, the only way that we can see to do this is to place a jar with our logic into the endorsed folder to ensure that the same instance is seen by the different wars (each one has its own classloader).
This jar makes use of the various caching functions of Google Guava and has been proven to work in unit tests and within the portlet container. However, we have found ourselves faced with a clash of different versions of Guava due to the endorsed classloader taking preference over the subsequent classloaders. The portlet container uses an early version of Guava and our portlets use our internal framework which uses a more recent version!
If we write our endorsed jar to use the same version of Guava as the portlet container then the framework boots but the portlets won't start as the API is different.
If we write our endorsed jar to use the same version of Guava as our own framework, then the portlet framework won't start because the API is different, so our portlets never load.
The approach we are trying at the moment is copying the Guava source code into our own jar under a new package - this has been done in various open source projects - for example the class com.google.common.base.Ascii would be repackaged com.mycompany.com.google.common.base.Ascii. This works, though it means recompiling Guava each time we make a new version of our endorsed jar.
We would prefer being able to automate the generation of this endorsed jar, and having seen documentation for using ProGuard with Guava in an Android context, have a feeling that Proguard might be able to help.
Is ProGuard capable of repackaging a jar dependency inside another jar, maintaining a single internal package hierarchy? Could the -flattenpackagehierarchy option do this?
Another option would be to use JarJar to repackage Guava so you don't have to recompile it from source every time.
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.
I'm fairly new to Java/Spring and am trying to put together a simple app which will include some basic CRUD operations and I'd like to use Hibernate for data access.
I'm using Maven as my build tool. My question is: how can I find out which dependencies are required to use Hibernate? For example, I'm using Spring 3.0.6, but how would I know what version of Hibernate to use with that version of Spring? More over, if there are multiple possible Hibernate dependencies, how would I know which ones to include for the functionality I need? So far this seems to be partially reading documentation and partially trial and error.
Is there a definitive way of knowing which Maven dependencies to use with certain version of other dependencies? Any which dependencies to use for particular bits of functionality?
Thanks,
James.
I follow these steps when starting to use a new framework:
Go to framework's web site. In your case hibernate web site and try to find latest (or a specific) version. For hibernate it is 3.6.8-Final at the time of writing.
Search for a maven dependency definition on the framework web site. If you can not find any dependency definition, them simply google for "frameworkname _version_ maven dependency" and you'll most probably find necessary definition, as well as the necessary repository information. For example you can find the dependency definition for hibernate on mvnrepository.com and necessary artifact repository information on Hibernate 3.6.8 release page:
The artifacts have all been published to the JBoss Nexus repository under the org.hibernate groupId at http://repository.jboss.org/nexus/content/groups/public-jboss/
The question of which dependencies are necessary and which are optional depends entirely on the framework to be used. So for example in order to use hibernate, as stated on Hibernate Quick Start Guide:
hibernate-core: The main artifact, which contains all the Hibernate classes, in packageorg.hibernate. You need these to build applications using the native Hibernate APIs. It includes capabilities for using native Hibernate mapping in hbm.xml files, as well as annotations.
About compatibility issues (which version of hibernate is compatible with spring 3.0.6), all I can say is you have to read about integration manuals for those frameworks. Since Spring and Hibernate are two exclusively distinct frameworks, I don't think you can find a constant location to look for version compatibility matrix or something like that.
The purpose of Maven is to avoid handling dependencies by hand. Just choose which version of Hibernate to use and include it in your pom; Spring supports many different versions.
If you know what parts of Spring you want to use, just include those parts in your pom; they'll include their own requirements.
Is there a specific module and/or version combination you're having an issue with?
The only way to know for sure that you've got all dependencies is by running your app.
Maven resolves for you transitive dependencies so you can quickly detect missing ones by compiling the java code.
However, in a web app there are many dependencies that are required in runtime only, so they are not detected at compilation time.
you can find out the dependencies by running mvn dependency:tree and analyze if they are required or not by running mvn dependency:analyze.
Taking the newest ones usally works as long as they are stable.
Start with hibernate and spring core, context, tx.
After you added some could you will probably recognize that something else is missing.
Try and error doesn't sound good, but its working pretty well for spring dependencies.
For my previous employer I've worked with Hibernate, and now that I'm in a small startup I would like to use it again. However, downloading both the Hibernate core and the Hibernate annotations distributions is rather painful, as it requires putting a lot of JAR files together. Because the JARs are split up into categories such as "required" and "optional" I would assume that every developer ends up with a different contents of his lib folder.
What is the common way to handle this problem? Basically I want to have a formal way to get all the JARs for Hibernate, so that (in theory) I would end up with exactly the same stuff if I would need again for another project next month.
Edit: I know roughly what Maven does, but I was wondering if there was another way to manage this sort of thing.
As Aaron has already mentioned, Maven is an option.
If you want something a bit more flexible you could use Apache Ant with Ivy.
Ivy is a dependency resolution tool which works in a similar way to Maven, you just define what libraries your project needs and it will go off and download all the dependencies for you.
Maybe this is not much of an answer, but I really don't see any problem with Hibernate dependencies. Along with hibernate3.jar, you need to have:
6 required jars, out of which commons-collections, dom4j and slf4j are more often used in other open-source projects
1 of either javassist or CGLIB jars
depending on cache and connection pooling, up to 2 jar files, which are pretty much Hibernate specific
So, at the very worst, you will have a maximum of 10 jars, Hibernate's own jar included. And out of those, only commons-collections, dom4j and slf4j will probably be used by some other library in your project. That is hardly a zillion, it can be managed easily, and surely does not warrant using an "elephant" like Maven.
I use Maven 2 and have it manage my dependencies for me.
One word of caution when considering using Maven or Ivy for managing dependencies is that the quality of the repository directly affects your build experience. If the repo is unavailable or the meta-data for the artifacts (pom.xml or ivy.xml) is incorrect you might not be able to build. Building your own local repository takes some work but is probably worth the effort. Ivy, for example, has an ANT task that will import artifacts from a Maven repository and publish them to you own Ivy repository. Once you have a local copy of the Maven repo, you can adjust the meta-data to fit what ever scheme you see fit to use. Sometimes the latest and greatest release is not in the public repository which can sometimes be an issue.
I assume you use the Hibernate APIs explicitly? Is it an option to use a standard API, let's say JPA, and let a J2EE container manage the implementation for you?
Otherwise, go with Maven or Ivy, depending on your current build system of choice.