I am new to apache camel and I am testing camel-jpa to poll from table and display records
Following is main class
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("LoanServicePU");
CamelContext camelContext = new DefaultCamelContext();
JpaComponent jpa = new JpaComponent();
jpa.setEntityManagerFactory(entityManagerFactory);
JpaTransactionManager myTM=new JpaTransactionManager();
myTM.setEntityManagerFactory(entityManagerFactory);
jpa.setTransactionManager( myTM );
jpa.setCamelContext(camelContext);
camelContext.addRoutes(new JpaRouteBuilder());
camelContext.addComponent("jpa",jpa);
camelContext.start();
Thread.sleep(10000);
camelContext.stop();
System.out.println("Done");
Following is jparouter class
public void configure() throws Exception {
from("jpa://com.pns.ab.model.LoanRequest?consumeDelete=false;"
+ "consumer.delay=2000;maxMessagesPerPoll=1000;"
+ "consumer.namedQuery=selectLoanRequests").to("stream:out");
}
I configured persistence.xml and its under META-INF, in fact in eclipse I start Java Project and then set JPA facet
persistence.xml
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="LoanServicePU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.pns.ab.model.LoanRequest</class>
<properties>
<property name="eclipselink.target-server" value="None"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#127.0.0.1:1521:xe"/>
<property name="javax.persistence.jdbc.user" value="vs"/>
<property name="javax.persistence.jdbc.password" value="vs"/>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
But I am getting following error:
[main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.12.3 (CamelContext: camel-1) started in 1.426 seconds
[Camel (camel-1) thread #0 - jpa://com.pns.ab.model.LoanRequest] WARN org.apache.camel.component.jpa.JpaConsumer - Consumer Consumer[jpa://com.pns.ab.model.LoanRequest?consumeDelete=false%3Bconsumer.delay%3D2000&consumer.namedQuery=selectLoanRequests] failed polling endpoint: Endpoint[jpa://com.pns.ab.model.LoanRequest?consumeDelete=false%3Bconsumer.delay%3D2000&consumer.namedQuery=selectLoanRequests]. Will try again at next poll. Caused by: [javax.persistence.TransactionRequiredException - joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.]
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.registerIfRequired(EntityTransactionWrapper.java:91)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.joinTransaction(EntityManagerImpl.java:2081)
From the log
resource-local EntityManager which is unable to register for a JTA transaction
I conclude that the camel route is deployed to a JTA transaction environment but that in your persistence.xml you may use the default transaction-type which is RESOURCE_LOCAL instead of JTA.
EDIT:
With following setup, I could make it work:
Don't init the EntityManagerFactory and TransactionManager yourself, just do:
final SimpleRegistry registry = new SimpleRegistry();
final CamelContext context = new DefaultCamelContext(registry);
context.addRoutes(new JpaSetupRouteBuilder());
context.start();
In persistence.xml rename your persistence-unit to camel such as:
<!-- setting the transaction-type to RESOURCE_LOCAL is optional as this is the default -->
<persistence-unit name="camel" transaction-type="RESOURCE_LOCAL">
Yes, I know, this is not very satisfying.
EDIT:
If you don't want to or are not able to rename the persistence-unit to camel then you could set its name in the URI using the persistenceUnit option such as:
from("jpa://com.pns.ab.model.LoanRequest?consumeDelete=false"
+ "&consumer.delay=2000;maxMessagesPerPoll=1000"
+ "&consumer.namedQuery=selectLoanRequests"
+ "&persistenceUnit=LoanServicePU")
.to("stream:out");
EDIT:
Or alternatively, use the Spring XML setup as described here.
Related
I have an empty persistenceUnit in my jar file:
<persistence-unit transaction-type="JTA" name="base1">
</persistence-unit>
<persistence-unit transaction-type="JTA" name="base2">
</persistence-unit>
My idea is to replace the empty persistenceUnit by a full persistenceUnit with properties and classes in my main project, like this:
<persistence-unit name="base1" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:jboss/datasources/myDS</jta-data-source>
<class>br.com.myproject.MyClass</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.cache.use_second_level_cache"
value="false" />
</properties>
</persistence-unit>
But when i try to start server i got the following error:
Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYJPA0038: Falha ao adicionar o serviço da unidade de persistência para base1
Caused by: org.jboss.msc.service.DuplicateServiceException: Service jboss.persistenceunit.myproject#base1.__FIRST_PHASE__ is already registered"}}
Is there any way to override the persistenceUnit ?
If you really need to dynamically override your persistence.xml, this might be best done during building.
my personal warning: it sounds like a configuration-hell to me and I'd rather suggest using a container-managed JNDI approach here.
But anyway:
Use 2 maven profiles.
And if you activate profile1, then persistence.xml from profile1 will be added at the right place. and if you activate profile2 persistence.xml from profile2 will be taken.
therefore use the copy-resources-mojo for maven.
https://maven.apache.org/plugins/maven-resources-plugin/examples/copy-resources.html
If just the values of parameters change, and not the whole structure,
then you can also just "filter" and replace strings during maven-processes
then you would define properties in the profiles.
https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
You can also add a basic persistence.xml to your project as a default file. So if no maven-profile is activated, this one will be used. (even though it might happen, that the app doesn't work as expected, if the data-resource is not configured correctly)
Spring provides an interface JpaVendorAdapter which allows to plug in any JPA vendor specific configuration through Spring Java config or XML configuration during application startup.
You can create an EntityManagerFactory instance with LocalContainerEntityManagerFactoryBean and any implementation classes of JpaVendorAdapter such as HibernateJpaVendorAdapter, EclipseLinkJpaVendorAdapter or OpenJpaVendorAdapter.
I believe you don't even need to define the empty persistence unit in persistence.xml if your application used Spring.
Below is the sample on how to create EntityManagerFactory with Spring Java config:
#Inject
private DataSource base1DataSource;
#Inject
private DataSource base2DataSource;
#Bean
public EntityManagerFactory base1EntityManagerFactory()
throws IOException, NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean containerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
containerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
containerEntityManagerFactoryBean.setPackagesToScan("YOUR_PACKAGE_NAMES");
containerEntityManagerFactoryBean.setJtaDataSource(base1DataSource);
containerEntityManagerFactoryBean.setJpaProperties(loadBase1JpaProperties());
containerEntityManagerFactoryBean.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
containerEntityManagerFactoryBean.setPersistenceUnitName("base1");
containerEntityManagerFactoryBean.afterPropertiesSet();
return containerEntityManagerFactoryBean.getObject();
}
#Bean
public EntityManagerFactory base2EntityManagerFactory()
throws IOException, NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean containerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
containerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
containerEntityManagerFactoryBean.setPackagesToScan("YOUR_PACKAGE_NAMES");
containerEntityManagerFactoryBean.setJtaDataSource(base2DataSource);
containerEntityManagerFactoryBean.setJpaProperties(loadBase2JpaProperties());
containerEntityManagerFactoryBean.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
containerEntityManagerFactoryBean.setPersistenceUnitName("base2");
containerEntityManagerFactoryBean.afterPropertiesSet();
return containerEntityManagerFactoryBean.getObject();
}
#Bean
public Properties loadBase1JpaProperties() throws IOException {
ClassPathResource resource = new ClassPathResource("base1-persistence.properties");
return PropertiesLoaderUtils.loadProperties(resource);
}
#Bean
public Properties loadBase2JpaProperties() throws IOException {
ClassPathResource resource = new ClassPathResource("base2-persistence.properties");
return PropertiesLoaderUtils.loadProperties(resource);
}
Please refer to the following URL for additional info on what you can override to your persistence.xml :
http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html
I assume you want to declare your persistent unit in a superclass and you want to define the persistent unit in a explicit project. If true you could use a JNDI approch like this:
<persistence-unit name="MyPersistenceUnit"
transaction-type="JTA">
<jta-data-source>java:/myDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<jar-file>Persistence.jar</jar-file>
<properties>
<property name="jboss.entity.manager.jndi.name" value="java:app/applicationEntitymanager"/>
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.show_sql" value="false" />
</properties>
</persistence-unit>
on the other side you can acces the Entitymanager with:
#Resource(mappedName = "java:app/applicationEntitymanager")
protected EntityManager em;
This is essentially a duplicate of How to locate the source of JBAS011470 error in JBoss?
But essentially, As soon as I add a second persistence unit, it gives me this error. It's ridiculous. I'm not going to disable the JPA subsystem like some people suggest - that sounds wrong.
My persistence.xml setup is as follows, where java:/NAME is set up as a datasource in standalone.xml:
<?xml version="1.0"?>
<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
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="name" transaction-type="JTA">
<jta-data-source>java:/NAME</jta-data-source>
<class>za.co.classes.A</class>
<class>za.co.classes.B</class>
<class>za.co.classes.C</class>
<properties>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="jboss.entity.manager.factory.jndi.name"
value="java:jboss/persistence/NAME" />
<property name="jboss.entity.manager.jndi.name"
value="java:jboss/persistence/em/NAME" />
<property name="hibernate.dialect" value="za.co.equrahealth.dao.SQLServerDialect" />
</properties>
</persistence-unit>
The error starts as soon as I add a second persistence unit. So spring context is irrelevant.
Well, I luckily have multiple databases within the same schema, so I came up with a workaround. But it's obviously not going to solve the problem when there are multiple schemas. I think the cause of this issue might actually be a bug in JBoss.
#PersistenceContext
private EntityManager entityManager;
private EntityManager getEntityManager(String source)
{
if ("a".equalsIgnoreCase(source))
{
entityManager.createNativeQuery("USE A_DB;").executeUpdate();
}
else
{
entityManager.createNativeQuery("USE B_DB").executeUpdate();
}
return entityManager;
}
I have Vaadin project with JPA 2.1 + EclipseLink + MySQL.
In eclipse in project settings I set connection to base and drivers correctly. Without problem I "generate Entities from Tables", but persistence.xml haven't info about driver, connection, login, pass to DB.
My auto generate persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="RadiologicalWarehouse">
<class>pl.intibs.rw.entitites.Message</class>
<class>pl.intibs.rw.entitites.Part</class>
<class>pl.intibs.rw.entitites.Role</class>
<class>pl.intibs.rw.entitites.Sample</class>
<class>pl.intibs.rw.entitites.SampleHistory</class>
<class>pl.intibs.rw.entitites.User</class>
</persistence-unit>
</persistence>
If I run my application with simple query, I get of course exception:
javax.servlet.ServletException: com.vaadin.server.ServiceException: javax.persistence.PersistenceException: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:239)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
If JPA has defined the connection in the project, why does not generate this persistence automatically?
Screenshot settings JPA: http://i.imgur.com/T2oEdHA.png
Based on what I understand you have set parameters for the Jpa plugin to eclipse and this is much different to set the parameters to persistence provider. Firstly you have to decide what persitent provide use and specify it in the persistence.xml together with the others paramenters.
This is an example of persistence.xml with eclipseLink:
<persistence>
<persistence-unit name="myUnit">
<provider>yourProvider</provider>
<class>it.myCompany.domain.MyFirstClass</class>
<class>it.myCompany.domain.MySecondClassClass</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="${driverClass}" />
<property name="javax.persistence.jdbc.url" value="${connectionURL}" />
<property name="javax.persistence.jdbc.user" value="${username}" />
<property name="javax.persistence.jdbc.password" value="${password}" />
<property name="eclipselink.logging.level" value="info"/>
</properties>
<shared-cache-mode>NONE</shared-cache-mode>
</persistence-unit>
</persistence>
I am getting the following exception:
javax.el.ELException: javax.persistence.TransactionRequiredException
at com.sun.el.parser.AstValue.invoke(AstValue.java:279)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
Caused by: javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:161)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:151)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:299)
I am using Hibernate 4.3.5
#Named
#SessionScoped
public class MenuBean implements Serializable {
#PersistenceContext
private EntityManager entityManager;
#Transactional
public void create() {
MenuTitle menu = new MenuTitle();
menu.setLabel(label);
entityManager.persist(menu); //exception in this line
label = null;
}
Persistence XML:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="MyPersistenceUnit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>MySQL5</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.current_session_context_class" value="jta"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</properties>
</persistence-unit>
I have also tried to set hibernate.transaction.jta.platform to org.hibernate.engine.transaction.jta.platform.internal.SunOneJtaPlatform but it results in the same error.
EJB CMT´s are working fine.
The Create action is called from a commandButton:
<p:commandButton value="Create" process="#this type" update=":megaMenuForm:mainMenu" actionListener="#{menuBean.create()}" oncomplete="closeMenuDialog(xhr, status, args)"/>
See EJB specs if you want to manage transaction. Inject a resource UserTransaction.
Also #Transactional with not do anything here since you are using EJB.
In general you example should work, and #Transactional annotation will be just ignored. Could you try to make an interface, and call create method through it?
Looks like you are using EJB 2 style coding, but Glassfish 4 implements EJB 3.1, so it is better to go with a new one.
I am trying to create a web app using JSF and EJB 3.0.
I am using plain JSF, Glassfish Server, Hibernate as my persistance provider. My database is apache derby.
Here my Stateless Session bean as follows:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class StudentServiceBean implements StudentService{
#PersistenceContext(unitName="forPractise")
private EntityManager entityMgr;
#Resource
private SessionContext sessionContext;
#Override
public List<StudentVO> fetchStudentListOrderByStudentId(boolean flag){
List<StudentEntity> studentList = null;
TypedQuery<StudentEntity> studentQuery = null;
List<StudentVO> studentVOList = null;
String queryDesc = "select s from StudentEntity s order by s.studentId desc";
String query = "select s from StudentEntity s order by s.studentId";
try{
if(!flag){
studentQuery = entityMgr.createQuery(query,StudentEntity.class);
}else{
studentQuery = entityMgr.createQuery(queryDesc,StudentEntity.class);
}
studentList = studentQuery.getResultList();
studentVOList = new ArrayList<StudentVO>();
for(StudentEntity studentE : studentList){
studentVOList.add(new StudentVO(String.valueOf(studentE.getStudentId()),studentE.getStudentName(),studentE.getContactNumber()));
}
}catch(Exception e){
System.out.println(" EXCEPTION IN "+this.getClass().getName()+" in method fetchStudentListOrderByStudentId "+e);
}
return studentVOList;
}
And this is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="forPractise" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/app</jta-data-source>
<class>com.entity.StudentEntity</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup" />
</properties>
</persistence-unit>
</persistence>
What happens is on load of the JSP page, the getter method of StudentList is called -
inside the getter method I have written logic that if studentList is empty then call the studentService.fetchStudentListOrderByStudentId(true);.
But when I do this I get an exception:
EXCEPTION IN com.bb.StudentServiceBean in method
fetchStudentListOrderByStudentId
org.hibernate.service.UnknownServiceException: Unknown service
requested
[org.hibernate.service.jdbc.connections.spi.ConnectionProvider]
Can you please tell me what I am missing, or where I am going wrong?
Thanks.
You indicate that you are using Hibernate 4.x, but the class you mentioned afaik is only valid for JPA 1.0 and Hibernate 3.x. Try removing the following line from your configuration:
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup" />
Just in case it's of any interest, I got this error on Jetty when trying to start a Hibernate session:
Unknown service requested [org.hibernate.service.jdbc.connections.spi.ConnectionProvider]
The root cause was a previous Exception (a few seconds earlier in the logs) which caused the spring context (WebAppContext) to fail to initialize.
Once I fixed the spring context, the "Unknown service requested" fixed itself. So, if you're seeing this error it's worth checking for earlier errors before investigating too much..