I am having some problems getting Hibernate and Spring up and running. I have a web server project which makes use of several other projects which have persistent entities in them. The problem I have is that I get a ClassNotFoundException for an entity class that is stored within another jar inside of WEB-INF/libs.
Do I need to have a persistence.xml for each jar that contains entity classes?
Please let me know if you need to see any configuration files.
Depending on your set up there are probably a number of different ways to solve this - and none them usually feel idea (IMO).
The essential problem is to do with ClassLoader isolation. There are rules as to what the files within a jar can access.
In your particular case, the easiest way to solve it is probably to put the persistence.xml within the parent web project. If you are not using persistence xml, you need to bootstrap hibernate/spring from the web project.
The parent web project should have access to all the libraries within its WEB-INF/lib whereas each of the jars in the libs folder may not have access to each other.
You could set up another persistence.xml in each jar but they would not be composited together into one persistence unit. You would need to use a different pu depending on which entity you wanted.
Related
How can I cache server-wide (with cache scope spanning multiple WARs on this server) instances of classes from a JAR which is contained binary-identical in several WARs on a web container (server, e. g. Tomcat)?
<EDIT> I want to cache application data across WARs because the data is common to them. (It's a portal project, where it can be useful to share common data across different "views" implemented as different portlets deployed as different WARs, and using a Java object cache is much faster and more simple than using a central data-holding service.) </EDIT>
Is that possible at all? Or is it required to put such a JAR on a path accessed by a common parent classloader, like in /lib/ext ?
See: Java, Classpath, Classloading => Multiple Versions of the same jar/project
See: How does class loading work when the same class exists in different applications on the same server?
See: cast across classloader?
See: What is a serialVersionUID and why should I use it?
Yes, the best option is to put the classes in a class loader that is a parent of the two applications. If by lib/ext you mean JAVA_HOME/lib/ext, then I would not recommend that. Instead, you should put them in CATALINA_HOME/lib directory. See the Shared Library Files section of the documentation, which links to the Class Loader HOW-TO documentation.
You can add common classes (jars) to the shared.loader property in conf/catalina.properties. Those classes are available to all web apps but not tomcat itself.
If you implement a cache around a static singleton, then you would be able to access the objects from different web apps. I don't know if that is best practice however. For example it makes it hard to scale because it makes it impossible to load balance the apps onto many servers.
The answer seems to be "it depends".
If the JAR(s) (or classes) in question do not have dependencies conflicting with other components also deployed on the server, both proposed solutions (CATALINA_HOME/lib/ext/ and CATALINA_HOME/conf/catalina.properties :: shared.loader) should plainly work. Thus both are "correct answers" and I cannot see which one is "more correct" than the other.
However I missed a crucial detail when I first asked the question (but this does not invalidate it): In my case the JAR in question required Spring 4.2.9.RELEASE (and other dependencies), but other relevant WARs deployed on the same server contain and require Spring 3.0.7. (The objects to be cached do not depend on Spring, but the JAR was not designed with this problem in mind, and it also contains other related code depending on Spring which now would be very difficult to separate.)
Generally it should be possible to put into CATALINA_HOME/lib/ext/ what ever you want as long as all already deployed WARs contain everything they need: The "module first / parent last" class loading policy should prevent conflicts, even if (as in this example) Spring 4.2.9 is available to the parent classloader and Spring 3.0.7 is available to the WAR classloader. But it looks somewhat "unclean" and messy to me to mix-up things that way.
Therefore I decided to use the "to-be-cached" object's classloader hash code as the key in a map, in which the cached data are the values. Then all cached data is selected "by classloader" which automatically and transparently ensures assignment compatibility. If there is also another WAR deployed on the server which can change and thus invalidate the cached data, it can remove the whole map from the cache, forcing the "read-access" WARs to reload data on next access.
However this approach DOES NOT allow cross-WAR cacheing: Effectively every WAR will get its own private cache segment.
Another approach would be to deliberately transform all data to cache to/from e. g. JSON so as to get a "naturally global" data type like java.lang.String for the cached data. If chosen from the beginning of the project, to me this seems to be the cleanest way, but if there is already a complex (and generally working) implementation in place, this may cause some work to do.
Comments on this self-answer are welcome!
I have several small java projects that access to same DB. Is it possible to have one persistence.xml file, which is somewhere on the file system (not included in any jars, wars, ears, etc.) and it is still visible to the projects? The reason is that there is a requirement that the persistence.xml has to be easily replaceable and configurable and the configuration has to be done on one place for all projects.
Sounds like a question somewhat similar to this: Package a runnable JPA jar putting persistence.xml outside
The answer appears to be no. However, if you were using Spring to bootstrap the persistence manager, you could wire the datasource independent of the persistence.xml and have the properties loaded from a centralized .properties file. Look at this answer for more ideas: loading .properties in spring-context.xml and persistence.xml
We have a team of 5 to 8 people and our project is using Hibernate (ORM) but we are facing some problems related to HBM files and there respective VOs (Value Objects). Actually we all are working on different modules and we all are creating HBM files and there respective VOs as per our module (so we have our HBM files and VOs specific to our module). If common table is used in more than one module then we have multiple HBM file and their VOs for that single table. So should we place all the HBM files anf VOs to a specific location or keep them module specific even if we have multiple HBMs and VOs. Please suggest the GOOD or BAD practice as well.
Thanks
From the query it seems each module has its own data access. If its not very complex, you can put all the data access in separate module. A project can have multiple modules but should have one place for data access.
As suggested, you can have a DAO module which is only doing to Data related operations.
Packages can be used to identify different DAO types.
The common DAO should be kept simple. Business Logic should not go in that. Logic should be handled at a higher level.
Other than that :-
Your project should be properly structured i.e. packages should be clearly defined.
module1/src/../com/../../bl
module2/src/../com/../../b0
dataacess/src/../com/../../bl
dataacess/src/../com/../../bo
Dependencies should be clearly extrapolated. If you have one DAO module then DAO should be independent. Other Modules should depend on DAO. If its java you can use maven to do this.
Finally its the choice we make. There will be lot of best practices. You should choose what suits best in your scenario. In the end it should be simple and manageable in future.
There should be a common project that will contain all DAO related stuff. Each module/project will include that commonDAO project in its classpath to perform hibernate and database related operations. This will overcome HBM files duplicacy and ease to maintain code.
I have a Java/Spring/Hibernate application with a payment module. Payment module has some domain classes for payment subscription and transactions etc. Corresponding hibernate mapping files are there. This module uses applicationContext.xml for some of the configuration it needs.
Also, This module has a PaymentService which uses a paymentDAO to do all database related work.
Now, I want to use this module as it is(without any or minimal re-writing) in my other application(Grails application). I want to bring in the payment module as a jar or copy the source files to src/java folder in Grails.
With that background, I have following queries:
Will the existing applicationContext.xml for Spring configuration in the module will work as it is in Grails? Does it merge with rest of Grails's Spring config?
Where do I put the applicationContext.xml? classpath? src/java should work?
Can I bundle the applicationContext.xml in Jar(If I use jar option) and can overwrite in Grails if anything needs to be changed? Multiple bean definition problems in that case?
PaymentService recognized as regular service? Will it be auto-injected in controllers and/or other services?
Will PaymentDAO use the datasource configuration of Grails?
Where do I put the hbm files of this module?
Can I bundle the hbm files in Jar(If I use jar option) and can overwrite in Grails if anything needs to be changed? Which hbms are picked? or, there will be problems with that?
Too many questions! :)
All these concerns are actually before trying. I am going to try this in next few days(busy currently). Any help is appreciated.
Thanks.
There are a couple of things you'll want to consider:
You'll need to package your applicationContext.xml to avoid namespace clashes - that is, you'll probably put it in src/resources/com/company/module/applicationContext.xml
This application context really needs to be compatible with the grails application - it'll need to access the DB connection used by your app - make sure it doesn't define its own - See section 14 of the docs - http://grails.org/doc/latest/guide/14.%20Grails%20and%20Spring.html
Section 15 of the docs - http://grails.org/doc/latest/guide/15.%20Grails%20and%20Hibernate.html describes using hibernate mapping files
15.4 points out some good articles - http://jasonrudolph.com/blog/2006/06/20/hoisting-grails-to-your-legacy-db/ and http://www.infoq.com/articles/grails-ejb-tutorial
Probably not the exact answer you were looking for, but I hope this helps.
I have classes that are named exactly the same across different plug-ins that I use for my application, and I'd like to be able to configure them properly with Hibernate. The problem is that it looks like Hibernate dynamically generates a class' package name when trying to find a class when it's doing its mapping. With one plug-in this scheme works, but across multiple plug-ins it's not working. It looks like Hibernate gets confused when dealing with Hibernate configuration files across multiple plug-ins.
Is this because each plug-in has its own class-loader? What is the best way to proceed to make this work with the existing plug-ins and Hibernate?
The problem is, that every plugin has its own Classloader and Hibernate uses Reflection to find the right classes.
I have a very nice article at home about exactly this problem, but this one is in German. I will try to explain what you need to do.
In order to have the datastructure shared over several plugins, you have to put it in a plugin and enable a feature called buddy-policy.
Lets say you have a main-application-plugin which is initiating hibernate on startup, this plugin needs to "see" the classes from the datastructure-plugin. To do this the main-plugin sets its Buddy-Policy to "registered" and the datastructure-plugin registers itself as a "buddy". Unfortunately you have to do this all directly in the manifest file, at least in 3.3 there was no way to do this in the editor.
Once this buddy-policy works, Hibernate will also.
I looked up my old application and here is how I did it.
The main-application (toolseye.rcp) is dependent on the hibernate plugin (de.eye4eye.hibernate) and the datastructure-plugin (toolseye.datastructures)
The hibernate-plugin specifies its buddy-policy as "registered"
The datastructure-plugin registers itself to the hibernate-plugin
Here are the important lines:
Hibernate-plugin de.eye4eye.hibernate
Eclipse-BuddyPolicy: registered
Datastructure-plugin toolseye.datastructures
Eclipse-RegisterBuddy: de.eye4eye.hibernate
Put those line directly in the MANIFEST.MF
Both plugins need to reexport their packages in order that the main application or whatever layer you have in between can use them.
Hope that helped.
Just to make this complete.
Instead of using Hibernate, EclipseLink could be used as JPA-provider in a Eclipse RCP application. EclipseLink is the former TopLink from Oracle and has been choosen to be the reference implementation for JPA 2.
The point for an RCP is, that EclipseLink is available as OSGI-Bundles (org.eclipse.persistence.jpa), and due to that it can load classes from another plugin without an additional buddy-policy.
Currently I was playing around, using the following project structure (Model-View-Presenter Pattern). The names in the brackets specify the dependecy plugins (not all are included, only the ones related to this question)
rcp.mvp.view (rcp.mvp.presenter /
rcp.mvp.model)
rcp.mvp.presenter (rcp.mvp.data -
data reexports the model, so this is
not needed here) *
rcp.mvp.data (rcp.mvp.data.mysql /
rcp.mvp.model / javax.persistence /
org.eclipse.persistence.jpa)
rcp.mvp.data.mysql - provides only
the mysql-jdbc-driver. has to be
inside the classpath
rcp.mvp.model
In this scenario, the JPA provider in the data-plugin is able to load the classes from the model-plugin without a buddy-policy.
*Note, the presenter is not dependent on any JPA packages since this is encapsulated by DAOs (the main reason why to use them still)
Links
User Guide
RCP example (unfortunately not using DAOs)
EclipseLink conceptual Webinar from live.eclipse.org