I have been spending the week attempting to integrate JPA / ServiceMix 4.5.1 / camel-jpa 2.10.4 / Blueprint together. I'm currently using OpenJPA, but am not tied to it. The version of aries jpa used by servicemix is 0.3.0.
The stack trace I cannot get past is:
org.osgi.service.blueprint.container.ComponentDefinitionException: Error when instanciating bean workoutEntity of class class [...].WorkoutEntity
at org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:271)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:708)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:60)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:219)[10:org.apache.aries.blueprint:0.3.2]
[...]
Caused by: <openjpa-2.2.0-r422266:1244990 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: [javax.sql.DataSource]
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:218)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
[...]
Caused by: java.lang.IllegalArgumentException: [javax.sql.DataSource]
at org.apache.aries.jndi.services.ServiceHelper.proxyPriviledged(ServiceHelper.java:348)
at org.apache.aries.jndi.services.ServiceHelper.access$700(ServiceHelper.java:65)
at org.apache.aries.jndi.services.ServiceHelper$1.run(ServiceHelper.java:285)
at java.security.AccessController.doPrivileged(Native Method)[:1.6.0_43]
[...]
I've attempted several variations. Here is my current configuration:
persistence.xml:
<persistence-unit name="customer1" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/prototypedb)</jta-data-source>
<class>...</class>
</persistence-unit>
camel-context.xml
<service id="PrototypeDB" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/prototypedb"/>
</service-properties>
<bean class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/prototype"/>
<property name="username" value="root"/>
<property name="password" value="..."/>
</bean>
</service>
<service ref="workoutEntity" interface="..."/>
<bean id="workoutEntity" class="...">
<jpa:unit index="0" unitname="customer1" />
<tx:transaction method="*" value="Required"/>
</bean>
Entity Bean (written in groovy)
#Entity
#Table(name='customer1')
#Slf4j
class WorkoutEntity implements IWorkoutEntity{
private EntityManager entityManager
WorkoutEntity(final EntityManagerFactory entityManagerFactory) {
this.entityManager = entityManagerFactory.createEntityManager()
}
#Handler
void create( #Body final String input) {
// ...
}
}
I've attempted multiple different implementations of a DataSource, including the BasicDataSource, org.springframework.jdbc.datasource.SimpleDriverDataSource, and com.mysql.jdbc.jdbc2.optional.MysqlDataSource. All cause the IllegalArgumentException.
I've also attempted to forego using JNDI and instead define the data source directly in the persistence.xml. This causes ClassNotFoundException in the OpenJPA bundle, as it is not importing the mysql driver. I'd prefer to define this in my camel-context.xml and would prefer to not re-bundle the OpenJPA jar.
You probably also need the aries JNDI features installed. This helps to call OSGi services via JNDI lookups. This should be the missing piece.
Related
I am new to hibernate, and I have been tasked with changing the ConnectionProvider from the hibernate default CP to either Hikari (preferred) or C3P0 in a legacy Java application that does not use maven as a repository. The database is PostgreSQL. The hibernate version is hibernate-release-5.2.10.Final. I have added hibernate-hikaricp-5.2.10.Final.jar to the classpath.
I have a pre-existing xml configuration file for hibernate. This has been working for several years, but the project wants to change to a "production ready connection pool". I have added/modified properties for the connection provider as follows:
<property name="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</property>
<property name="hibernate.hikari.minimumIdle">5</property>
<property name="hibernate.hikari.maximumPoolSize">20</property>
<property name="hibernate.hikari.idleTimeout">30000</property>
I am getting the following StrategySelectionException (long stack trace reduced to exceptions/causes ... more information available if necessary).
Exception in thread "DatabaseCache initialize thread" org.hibernate.service.spi.ServiceException: Unable to
create requested service [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
...
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.hikaricp.internal.HikariCPConnectionProvider] as strategy [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
I made one other change, after first seeing the exception. I added the following property, but it made no difference.
<property name="hibernate.implicit_naming_strategy">default</property>
The full configuration, with some information provided as variables replaced during build, is:
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.implicit_naming_strategy">default</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</property>
<property name="hibernate.hikari.minimumIdle">5</property>
<property name="hibernate.hikari.maximumPoolSize">20</property>
<property name="hibernate.hikari.idleTimeout">30000</property>
<property name="hibernate.connection.username">${db_user_name}</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.url">${db_connection_url}</property>
<property name="hibernate.hbm2ddl.auto">none</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.jdbc.time_zone">GMT</property>
<property name="hibernate.generate_statistics">false</property> <!-- This affects performance, use only in development -->
<property name="show_sql">false</property>
</session-factory>
</hibernate-configuration>
Any strategies :D to address this would be welcome. Thanks.
everybody!
I've been trying to find the answer for some time but I didn't manage.
I try to configure my application and make it work under JBoss Application Server 7.1.1, using Enterprise Java Beans. My application is Web application, it uses servlets and injects other classes as EJBs. The problem is that every statement gets commited, so that means no transaction management is supported.
In my test example I have an entity with a collection of children (mapped with a relationship OneToMany with a property CascadeType.ALL). If a record in a collection has some problems (e.g. non-existing foreign key), it can't be inserted into table and throws exception. However, the parent entity gets inserted, so I assume the inserts are done in different separate transactions. This is strictly undesired behavior and I try to resolve it.
Technical parameters:
DBMS: Oracle EE 11g
AS: JBoss AS 7.1.1
my persistence.xml:
<?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/">
<persistence-unit name="OracleEntityManager">
<jta-data-source>java:jboss/CmaDevDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.jdbc.batch_size" value="20" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
</properties>
</persistence-unit>
</persistence>
my EJB:
#Stateless(name="EntityWriter")
#TransactionManagement(TransactionManagementType.CONTAINER)
public class EntityWriter {
#Resource
private SessionContext context;
/*#Resource
UserTransaction ut;*/
#PersistenceContext(unitName = "OracleEntityManager",type=PersistenceContextType.EXTENDED)
EntityManager em;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public EntityMarker insertEntity(EntityMarker entity)throws Exception
{
try
{
entity = em.merge(entity);
em.flush();
return entity;
}
catch (Exception e)
{
context.setRollbackOnly();
e.printStackTrace();
return null;
}
}
}
Actually I tried both EJB approaches: Container Management Transaction and Bean Management Transaction and neither works as I expect.
When I inject the bean into servlets I do it like this:
#EJB(name = "EntityWriter")
private EntityWriter entityWriter;
Now I think the bean is fine, probably something is missing in persistence.xml.
Would be grateful to any ideas. Thanks in advance!
Everything works correct after I edited Datasource configuration via JBoss Administration console and set a checkbox "Use JTA". It was unchecked by default.
You're right, Chris. Thanks!
I have a core library that has an interface that I want to expose as an OSGI service in Fuse ESB (Apache ServiceMix and Karaf). The goal is to allow other bundles to use it. The service uses JPA (OpenJPA) and Spring. The following is the interface:
public interface PatientService {
public Patient find(Integer id);
}
and the class:
#Repository
public class PatientServiceJpaImpl implements PatientService {
#PersistenceContext(unitName="psu")
private EntityManager entityManager;
#Override
public Patient find(Integer id) {
return entityManager.find(Patient.class, id);
}
}
The following is an abbreviated META-INF/spring/beans.xml:
<beans xmlns="http://www.springframework.org/schema/beans" ...>
<context:annotation-config />
<context:component-scan base-package="..." />
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="psu" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
And the META-INF/persistence.xml (also abbreviated):
<persistence xmlns="http://java.sun.com/xml/ns/persistence" ...>
<persistence-unit name="psu" transaction-type="RESOURCE_LOCAL">
<class>...</class>
</persistence>
In a non-OSGi environment, everything works great. It uses the felix maven-bundle-plugin, so to create the OSGi service, I added the following OSGI-INF/blueprint/osgi-context.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<bean id="patientService" class="com.test.service.PatientServiceJpaImpl" />
<service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" />
</blueprint>
The bundle is deployed successfully and the service is registered. The problem is that when the PatientService is referenced from another bundle, the entity manager has not been injected, thus throwing a NullPointerException in the find(Integer id) method. The following is a snippet of the consumer's META-INF/spring/consumer-context.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="patientServiceImpl" class="com.test.ws.PatientWebServiceImpl" >
<property name="patientService">
<osgi:reference interface="com.test.service.PatientService"/>
</property>
</bean>
...
</beans>
Just to be clear, the PatientService is injected in the consumer bundle, but the entity manager is not injected in the provider bundle. Also, it does not appear to be an issue with the persistence unit due to the following log output when starting the original service:
125 psu TRACE [SpringOsgiExtenderThread-14] openjpa.Runtime - org.apache.openjpa.persistence.PersistenceProviderImpl#24a5031d creating container org.apache.openjpa.persistence.EntityManagerFactoryImpl#4d6f77b6 for PU psu.
To get an idea what is going on, I logged the the object memory reference and stack trace in the constructor of the PatientServiceJpaImpl class. The constructor was called twice (creating two different objects):
The first output appears to originate from the osgi container starting from org.apache.felix and more or less ending in org.apache.aries.blueprint.
The second output appears to originate from the spring framework starting from org.springframework.osgi and more or less ending in org.springframework.beans.BeanUtils.
When the consumer service is called, the reference it has is to the blueprint instantiated object, which does not have an injected entity manager. Also from the logs, the persistence unit is instantiated after the blueprint instantiation of the PatientServiceJpaImpl object.
I have searched and tinkered with this issue for quite a while and I've run out of ideas. The irony is that it actually worked at one point, but I had made so many changes to get it to work that it was a rats nest that I was not able to back out of successfully.
Why is the persistence context not injected in the blueprint managed object? Any ideas will be appreciated. Thanks.
I'm not sure if this is going to work, cause you are mixing spring with blueprint. I have a working application based only on blueprint and I'm quite happy. For your use-case I'd suggest using blueprint at least for your JPA part. You still can use spring-dm for using the jpa classes as services.
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0">
<bean id="patientService" class="com.test.service.PatientServiceJpaImpl" >
<jpa:context property="em" unitname="dn1" />
<tx:transaction method="*" value="Required" />
</bean>
<service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" />
</blueprint>
Your PatientServiceJPAImpl I would change to not contain any annotations.
public class PatientServiceJpaImpl implements PatientService {
protected EntityManager em;
#Override
public Patient find(Integer id) {
return em.find(Patient.class, id);
}
}
A good way to deal with this would be to use Gemini JPA. With Gemini JPA, your JPA bundle would automatically expose an EntityManagerFactory OSGi service, based on the configurations in your persistence.xml. Thus, in the JPA client bundle, the blueprint just needs to import this service with a filter condition specifying the persistence unit name.
Here's a small implementation on those lines: mvc-osgi
If the EMF service doesn't work for you, you can use the EntityManagerFactoryBuilder service exposed by the Gemini JPA bundle to manually create the EMF. This would require calling the "createEntityManagerFactory".
I'm trying to do a simple persistence test using:
IntelliJ IDEA,
Maven,
Google Guice,
GWT,
EclipseLink and JPA 2.0.
My persistence.xml:
<persistence-unit name="guiceTest" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>utfpr.edu.br.server.model.Contato</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://127.0.0.1:5432/gwt"/>
<property name="javax.persistence.jdbc.password" value="postgres"/>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
The exception:
[EL Warning]: 2012-06-21 10:18:32.846--The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units. Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element
java.lang.IllegalArgumentException: Object: Contato{dataNascimento=Thu Jun 21 10:18:31 BRT 2012, id=null, nome='abcd', sobrenome='adsada', numero='12313123', email='lololol#gmail.com'} is not a known entity type.
The test class:
Injector i = PersistenceTestModule.getInjector();
private ContatoDao dao = i.getInstance(ContatoDao.class);
#Test
public void testSave() throws Exception {
Contato cont = new Contato("abcd","adsada","12313123","lollollo#gmail.com",new Date());
dao.save(cont);
assertNotNull(cont.getId());
}
My persistence.xml is corrected placed in resources/META-INF.
I read that is a eclipselink bug here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=338837
They said:
Solution:
There are two ways into this problem.
1) We specify no entities at all and also do not specify
false
- the result of this is a completely empty metamodel
2) We specify only part of the entities via properties
- the result of this is selective IllegalArgumentException errors thrown when
we attempt to use the missing EntityType classes - likely in a Criteria API
query".
I already tried this two solutions but I still got this error.
Please someone help me!
I am using JBoss AS 7.1.1 and able to configure a new JTA datasource and wire it to my EJB using
#PersistenceContext(unitName="TestPU")
private EntityManager entityManager;
When I tried to use RESOURCE_LOCAL PersistenceUnit I am getting the error saying I can't inject RESOURCE_LOCAL PU using #PersistenceContext.
I have configured my persistence.xml as follows:
<persistence-unit name="TestPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/xy"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="blah"/>
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
And in my DAO,
#Stateless
public class UserDAO {
#PersistenceContext(unitName="TestPU")
private EntityManager entityManager;
}
When I deployed my app on AS 7.1.1 I am getting the following error.
JBAS011428: Cannot inject RESOURCE_LOCAL container managed EntityManagers using #PersistenceContext
at org.jboss.as.ee.component.deployers.ModuleJndiBindingProcessor$1.handle(ModuleJndiBindingProcessor.java:169)
at org.jboss.as.ee.component.ClassDescriptionTraversal.run(ClassDescriptionTraversal.java:54)
at org.jboss.as.ee.component.deployers.ModuleJndiBindingProcessor.processClassConfigurations(ModuleJndiBindingProcessor.java:162)
at org.jboss.as.ee.component.deployers.ModuleJndiBindingProcessor.deploy(ModuleJndiBindingProcessor.java:155)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
... 5 more
Any solution to use RESOURCE_LOCAL PU with #PersistenceContext?
JTA : In Java EE environment, transactions are managed by the container & by default its JTA transaction. You can get entity manager by lookup or injection.
RESOURCE_LOCAL : In Java SE, application have to manage transactions explicitly & resource local transactions are native transactions. You have to create EntityManagerFactory & then can create entity manager from it.
As you are deploying it in application server, change the transaction-type to JTA in persistence.xml.