Liferay JPA ClassLoader Error - jpa

EDITED (I'm simplifying as my original question was too convoluted):
Create a portlet plugin in Liferay 6.1.20
Add in your portlet's web.xml a spring context loader
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Add in your application context an instance of an EntityManagerFactory
<bean id="localEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="WEB-INF/classes/META-INF/persistence.xml" />
</bean>
Make sure in your persistance definition you're referencing a JPA Implementation
<persistence-unit name="casd" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<properties>
<property name="eclipselink.weaving" value="false" />
</properties>
</persistence-unit>
Watch Tomcat cry
java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.eclipse.persistence.jpa.PersistenceProvider.getProviderUtil()Ljavax/persistence/spi/ProviderUtil;" the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, org/eclipse/persistence/jpa/PersistenceProvider, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for interface javax/persistence/spi/PersistenceProvider have different Class objects for the type javax/persistence/spi/ProviderUtil used in the signature
Play with hibernate3.jar, eclipselink.jar, persistence.jar until exhaustion, and realize Liferay is grinning at you.
How would you erase that irritating smile from Liferay's face?
In other words,
How can I get a JPA provider instantiated in a spring context within a portlet plugin in liferay 6.1.20 without getting a classloader error?

Ok. I managed to "solve" the problem moving ecliseplink.jar from /ROOT/WEB-INF/lib to {tomcat}/lib/ext
I don't like it as a solution, having to mess with ext, but it's a take it or leave it situation.

Related

JSF2 + Spring 4 + CDI + Spring Data, good match?

Let me tell you my story, and in between I will ask questions
I am working in a project I have to use JSF, there is not really other choice.
Coming from the wonderful Spring world in the last years, I really wanted to use some features like Spring Data, Spring singleton beans, Autowire beans into other beans, etc.
So I thought initially everything would be smooth, JSF (backing beans) will be managed by CDI container and #Service, #Respostory and database connection Entity manager by spring container. I want to make my application independent from a Java EE container, but just for information I am using Wildfly 9. In Wildfly, I create a datasource (connection to an oracle database) to bind later to my application.
So my first difficulty was, Some years ago, I code some JSF and I knew about #ManagedBean anotations and JSF scopes, all even though has not changed, there seems to be another aproach, and acording to what I read it is recommendable to use #Named and so on (CDI annotations) instead of the JSF annotations. So I wanted to follow those advices and somehow forces me to introduce CDI container into my application.
1st Question: Is that true ? Isn´t it recommendable to use old JSF annotations ?
My JSF beans look like this:
import java.io.Serializable;
import java.util.Locale;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.validation.constraints.NotNull;
import co.com.psl.connectnetwork.service.AuthenticationService;
import lombok.Data;
#Named
#SessionScoped
#Data
public class LoginBean implements Serializable {
}
My first issue, is that as I mentioned before, I wanted to introduce Spring, so I had in my application context xml file
<context:annotation-config />
<context:component-scan base-package="co.com.package" />
That was causing me problems because it seemed that Spring scanned my JSF managed beans , and treated them as Spring beans, which I don´t have any issue with that, but in practice those beans were singleton !!! , so terrible for an application which manages some state among logged users.
So I solved it by excluding JSF beans from spring container, I did it by introducing this:
<context:component-scan base-package="co.com.scannedpackage" >
<context:exclude-filter type="regex" expression="co.excludedpackage.*Bean" />
</context:component-scan>
So It did not seem to me so terrible , and as it seems to be some imcompatibility I though It was better that JSF beans will not be managed by Spring.
2nd Question: Do you agree?
As I said, I will have some #Service (Spring annotations) beans which I will eventually have to inject into the JSF managed beans . Initially I used #Inject to inject the service bean into the JSF bean , and it worked perfectly , the only issue is that when the JSF bean was using javax.enterprise.context.SessionScoped , it forced that all attributes are Serializable, so I made the #Service Spring bean implement the Serializable interface, which I dont think it is nice , even if it works, it seems to me a contradiction and a spring singleton bean (stateless) is forced to be serialized. So I tried to use the #Autowired anotation in the JSF managed bean , but the bean was not been injected and I got a null reference. Basically I guess the error I think it was, to use #Autowired in a bean which is not managed by spring.
3rd Question: How can I make it work ? I really think it is better to use #Autowired than to have spring beans serializable .If the ApplicationScope/viewScope/SessionScope JSF bean is passivated, will the Spring bean be injected again?, I don´t think so. If #ManagedBean is used, will it work ?
Another issue I am having, is that if my JSF beans are managed by CDI, It seems that javax.faces.bean.ViewScoped does not work well with CDI
4th Question: Is that so? Do you recommend me to use #ManagedBean instead of #Named? If I use #ManagedBean, how do I inject Spring dependencies? Is there any other CDI scope I could use instead of ViewScoped?
Now moving from JSF to Spring, I really want to use Spring in my applications, Features like Spring-Data, Spring-Security and others, the advantages of Spring singleton beans over EJB Stateless beans, are things I don´t want to miss. In my application, I will have a datasource created in the Java EE server or Java EE container. Then, I will bind that datasource internally in my application. So in my applicationContext.xml, I have:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<bean id="datasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/jndi-spring"/>
<property name="lookupOnStartup" value="true"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>
<!-- <jee:jndi-lookup id="datasource" jndi-name="java:/ConnectNetworkDS"/> -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="persistenceUnitName" value="persistenceUnit2" />
<property name="packagesToScan" value="co.com.packagestoscan" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
</bean>
<jpa:repositories base-package="co.com.packagewhererepositoriearelocated" />
</beans>
Please note that I am using Spring data and this line
<jpa:repositories base-package="co.com.packagewhererepositoriearelocated" />
is to indicate the interfaces annotated with #org.springframework.stereotype.Repository.Resository
Unfortunately, when I deploy my application, I get:
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service jboss.deployment.unit."deployedwar.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."deployedwar.war".WeldStartService: Failed to start service
So I was doing so internet research, and I included :
persistence.xml
CdiConfig class
The content of persistence.xml is:
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="persistenceUnit">
<class>co.com.entityClass1</class>
<class>co.com.entityClass2</class>
<jta-data-source>java:/jndi-string</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
</properties>
</persistence-unit>
</persistence>
And CdiConfig class:
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class CdiConfig {
#Produces
#Dependent
#PersistenceContext
private EntityManager entityManager;
}
5th Question: Can somebody please tell me why this is required ? Shouldn´t spring be able to inject the enntityManager into the #Repository Spring beans ? Why a persistence.xml is necessary ? Why does it seems that injection into #Repository Spring beans have to be done by Spring ? I think this somehow is redundant
Isn´t it recommendable to use old JSF annotations?
That's true. In JSF we're moving away from the JSF native beans and injection in favor of CDI. Although still not officially so, #ManagedBean and friends should be considered effectively deprecated.
#ViewScoped should work fine with CDI, but make sure you're importing the right one. The old one does not work, the newer one does. The one you need is:
javax.faces.view.ViewScoped
See CDI compatible #ViewScoped

JPA 2-level caching

Sorry for a providing a less specific title. Actually I am in a mess.
My actual problem: To improve performance of the application.
Good Thing: The data is inserted/updated through JPA through out the application.
Technology used so far: Spring 3.2 framework with JPA 2.0 and hibernate 3.2.
So far we don't have a direct dependency on Hibernate anywhere in our code.
Coming back to the problem:
I am planing to implement 2nd level Query caching for some queries which always fetch same data (dropdown values).
My 1st question :Does JPA provides 2nd level caching by itself(without using EHcache or any such dependency)?
What I found so far is using this property we can enable 2nd level caching
query.setHint("org.hibernate.cacheable", true);
My 2nd Question: Do I need to provide dependency for Ehcache or Hibernate-Ehcache is enough?
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.0.0</version>
</dependency>
or should I also need to provide
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcacheVersion}</version>
</dependency>
My third question: What are the properties I need to add in my persistence.xml.
I am sure about these two properties:
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
=====Thanks for the answer.This is the update might help the fellow developers.====
I am putting down the properties needs to be defined for enabling EHcache as lots of people face this exception
Caused by: org.hibernate.cache.NoCachingEnabledException: Second-level cache is not enabled for usage [hibernate.cache.use_second_level_cache | hibernate.cache.use_query_cache]
because of property mismatch and dependency mismatch.
The following property should work for hibernate 4.x along with Ehcache 2.4.3
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.cache.provider_configuration_file_resource_path" value="classpath:ehcache.xml" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
My 1st question :Does JPA provides 2nd level caching by itself (without
using EHcache or any such dependency)?
No, it doesn't. JPA is just a standard and doesn't provide any implementation. Hibernate provides implementation for JPA (EntityManager, EntityMangerFactory, etc) along with its own ORM implementation (Session, Session Factory, etc). Therefore, you need EHCache to support 2nd level cache. However, you can use JPA annotations/config for caching but that requires changes in persistence.xml.
Following two links explains each configuration options:
Caching using Hibernate specific classes/annotations.
Caching using JPA specific classes/annotations (with Hibernate as JPA provider)
My 2nd Question: Do I need to provide dependency for Ehcache or
Hibernate-Ehcache is enough?
You need to add ehcache-core, hibernate-ehcache and slf4j-simple (EHCache uses slf4j for logging). For dependencies details, check Hibernate EHCache Maven Dependencies section on this link.
My third question: What are the properties I need to add in my
persistence.xml.
If you go by JPA way, then the sample persistence.xml would be like:
<persistence-unit name="FooPu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
...
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
...
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
</properties>
</persistence-unit>

Running Hibernate in an Eclipse plugin-based environment

Lately, I have been trying to use Hibernate as O-R-Mapper for a project based on Eclipse bundles.
Because of the unique class-loading of Eclipse-bundles, many people advise using Eclipselink instead of Hibernate.
Having tried Eclipselink and being not quite satisfied with it, I do want to know:
Isn't there a way to get Hibernate up and running in my Eclipse Plug-In Project?
Here is a small walk-through of how I got it to work. Please feel free to ask questions and post suggestions on how to improve this:
Download Hibernate 4.2.5 or newer, which comes with OSGi-Support (see Hibernate OSGi Documentation). However, the examples there use Apache Felix as OSGi-implementation and not equinox.
Create a new Plug-In Project from existing jar-archives.
In my case, I added the following jars:
hibernate-core-4.2.5
hibernate-osgi-4.2.5
hibernate-commons-annotations-4.0.2 (i am using annotations)
hibernate-jpa-2.0 (i am using the java persistence api for more flexibility)
hibernate-entitymanager-4.2.5 (also the more generic jpa entitymanager instead of hibernates session)
org.osgi.core-4.3.1 (for the osgi classes)
jboss-logging
jboss-transaction-api
dom4j-1.6.1
antlr-2.7.7
Open the MANIFEST.MF of the project and add the following:
Bundle-Activator: org.hibernate.osgi.HibernateBundleActivator (this is hibernate's bundle activator from the hibernate-osgi bundle)
Bundle-ActivationPolicy: lazy (so that osgi passes the context to the bundle once it is activated)
Eclipse-BuddyPolicy: registered (we need this later to make our entity classes known to hibernate and vice versa)
Also make sure all your jars are on the Bundle-Classpath and all packages of the plug-in are exported.
Now, create a new plug-in project for your hibernate configuration and DAO.
Put your persistence configuration file (persistence.xml or hibernate.cfg.xml) in the META-INF folder at the root of your plugin. Here is an example for the persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_1.xsd"
version="1.0">
<persistence-unit name="TheNameOfMyPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<description>My Persistence Unit</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>de.eicher.jonas.SomeClass</class>
<class>de.eicher.jonas.AnotherClass</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
<property name="hibernate.connection.url" value="jdbc:derby:C:/Temp/data;create=true"/>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="org.hibernate.FlushMode" value="commit" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.current_session_context_class" value="thread"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Add org.eclipse.core.runtime to your dependencies and create an Activator to get static access to the BundleContext:
import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;
public class HibernateJpaActivator extends Plugin {
private static BundleContext context;
#Override
public void start(BundleContext context)
throws Exception {
HibernateJpaActivator.context = context;
}
public static BundleContext getContext() {
return context;
}
}
In your DAO or Util class, use the following code to get the EntityManagerFactory or EntityManager:
BundleContext context = HibernateJpaActivator.getContext();
ServiceReference serviceReference = context.getServiceReference( PersistenceProvider.class.getName() );
PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService( serviceReference );
emf = persistenceProvider.createEntityManagerFactory( "TheNameOfMyPersistenceUnit", null );
EntityManager em = emf.createEntityManager();
Only a few more things to do, before it works:
Open the MANIFEST.MF and make sure that your bundle receives the BundleContext on activation.
Bundle-ActivationPolicy: lazy
Bundle-Activator: my.package.name.HibernateJpaActivator
Open the plug-in containing your entities and add a dependecy to the plugin with your hibernate jars (the first one we created).
Now we also need the entities to be known in the plugin with the hibernate jars. We can't add a dependency there, because this would produce a cyclic dependency. Fortunately, Eclipse provides us with a workaround:
Open the MANIFEST.MF of your entity-bundle and register your hibernate-jar plugin as a buddy:
Eclipse-RegisterBuddy: org.hibernate4.osgi (the name of your hibernate plugin, the one where you set Eclipse-Buddy-Policy: registered)
Now Hibernate knows our classes and our classes know Hibernate. We also made sure, that Hibernate finds our persistence.xml (or hibernate.cfg.xml) and creates our readily configured EntityMangerFactory (or Session).

EclipseLink : No Persistence provider for EntityManager

I am trying to develop a web application. I started creating a Play! Framework project in Eclipse.
For the model part I chose to use JPA and since I had already created the database I was searching a way auto-generate the model classes.
I converted it to faceted form and used Dali to create the mapping with the database. During the configuration I was promted to chose a JPA implementation so I chose EclipseLink 2.1.3 Helios as a user library.
All the jars where added in my project.
After searching for similar errors, I modified the persistence.xml to:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="StudentApplication">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>models.Grade</class>
<class>models.GradePK</class>
<class>models.Student</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/studentapplication"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
</properties>
</persistence-unit>
</persistence>
The exact error I am getting now is:
Execution exception (In /app/controllers/class.java around line 98)
PersistenceException occured : No Persistence provider for EntityManager named jpa
I have to note that in application.conf I have declared the db connection and when I run the application I get
22:03:53,084 INFO ~ Connected to jdbc:mysql://localhost/studentapplication?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8_general_ci
Finally the file structure is:
-controllers
-models
-views
-META-INF
|_persistense.xml
As you may have understood (besides my rep) I am a newbie in web application development and specifically in JPA. I would be more than grateful to any kind of help. I apologize in advance if I posted not-needed information or if I missed mandatory information. Thank you for your time.
Thomas
It seems that you are referencing the persistence unit in your application by a different name than in your persistence.xml. Your persistence unit is named "StudentApplication" in persistence.xml. However, the error states that it is named "jpa" in your application.
Assuming that you are using application managed entity manager, there must be a line like this in your app:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa");
Change it to
EntityManagerFactory emf = Persistence.createEntityManagerFactory("StudentApplication");

Problems with classpath between Eclipse, Tomcat and JUnit in Spring 3 app

I have web app, based on Spring 3.0.3, that I've been developing using Eclipse 3.4. While doing so I've been running the web app in Tomcat 6.0.18 from Eclipse. That is, I have Eclipse use the Tomcat installation meaning that Tomcat will, as need, modify files etc. (at least, that's my understanding of what it's doing).
My problem is specifying the values for the contextConfigLocations in the web.xml. When running from within Eclipse this worked fine:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
classpath:applicationContext-security.xml
</param-value>
</context-param>
However, when I package the app into a war file (ROOT.war) and then added it to Tomcat's webapp directory and the try to start Tomcat, I get an error that neither of these applicationContext files can be found. But when I change it to below, Tomcat can find the files:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/applicationContext.xml
/WEB-INF/config/applicationContext-security.xml
</param-value>
</context-param>
I should note that applicationContext.xml includes other applicationContext files that also use the classpath: short hand. When running within Tomcat, I need to drop all use of classpath: in favor of relative paths to get Tomcat to see these files.
Great. Tomcat and Eclise are getting along nicely. But JUnit 4.7 is no longer happy. For whatever reason, files specified using #ContextConfiguration in a test class can't be found unless the classpath: short hand is used. Here is an example:
#ContextConfiguration(locations = {"classpath:applicationContext.xml", "classpath:applicationContext-security.xml"})
public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
#Test
public void testCreateUser() {
}
So applicationContext.xml and applicationContext-security.xml are found without a problem; however, property files that are specified in applicationContext.xml are not found.
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>/WEB-INF/config/spring/base.spring-config.properties</value>
<value>/WEB-INF/config/spring/local.spring-config.properties</value>
</list>
</property>
</bean>
But if I specify the location of these files using the classpath: short hand, the property files are found. If I do this though, the files won't be found when running from a war file in Tomcat.
For now I've created a applicationContext-test.xml that is a cut-and-paste conglomeration of all of the other applicationContext files wherein I'm using the classpath: short hand. This seems hacky and error prone and I'm wondering what the issue might be across all of these technologies.
Feedback most welcome!
web.xml content should look like
<context-param>
<description>
Spring Context Configuration.
</description>
<param-name>contextConfigLocation</param-name>
<!-- spring loads all -->
<param-value>
classpath*:spring/*.xml,
classpath*:spring/persistence/*.xml,
classpath*:spring/webapp/*.xml</param-value>
</context-param>
see http://static.springsource.org/spring/docs/2.5.x/reference/resources.html#resources-app-ctx-wildcards-in-resource-paths for further reference
the junit config should follow the same convention with classpath*:
but beware spring might load .xml context files you don't want it to do