I have earlier worked with application-managed RESOURCE-LOCAL transaction but now I want to use container-managed JTA transaction. Everything seems to be ok while I am using #Stateless but as soon as I use #Stateful I get an exception as below
javax.ejb.EJBException: javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
I am using JBoss eap 6.2 with eclipselink2.5 and Java8 and Oracle.Here are my codes
#Stateful
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class LoginDetailService {
#PersistenceContext(unitName="OracleDB", type=PersistenceContextType.EXTENDED)
protected EntityManager em;
public void addLoginDetails(String email, String pwd){
LoginDetail ld = new LoginDetail(email,pwd);
em.persist(ld);
}
#Remove
public void finished(){}
}
My Servlet code
#WebServlet("/signup")
public class SignUpServlet extends HttpServlet {
#EJB LoginDetailService bean;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = "EMAIL",
pwd = "PASSWORD";
bean.addLoginDetails(email, pwd); //exception occurs here
response.getWriter().println("Successful");
}
}
And my persistence.xml file
<?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="OracleDB" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:jboss/jdbc/OracleDB</jta-data-source>
<class>com.entity.Student</class>
<class>com.entity.LoginDetail</class>
<properties>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>
Plz hekp and guide me where I am going wrong. Thanks
Finally after working a lot, I found the problem. Actually there was no issue with my code, it was because of the JBoss server. I tested the same application with Glassfish4 and it worked perfectly.
REASON
The annotation #EJB has no effect in JBoss. Though you will see that a JNDI binding has occurred with the bean but when you will try tp persist, it wont work.
SOLUTION
To make it work on JBoss instead of #EJB, you will have to do a JNDI lookup and carry out the transaction. But the lookup for some reason failed on my desktop but worked fine on laptop may be due to some weird server configuration.
Another and better solution which I feel is to use another server like Glassfish or WebLogic where #EJB works fine and not a single bit of extra coding.
Related
I am total newbie in Java and EE especially. I started an EE project that should provide REST API which will handle 2 entities in remote Oracle Database. I am using NetBeans because it is the only way how to accomplish anything in Enterprise Java (as I see it now).
What I've done:
I created JDBC pool in Glassfish (v4.1-13). I can ping the pool successfully. Then I created JDBC Resource for the pool.
I generated Entity classes for the two entities I need to handle.
<persistence version="2.1" xmlns...>
<persistence-unit name="semestralka-ejbPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/dbs</jta-data-source>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.Food</class>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="Oracle"/>
</properties>
</persistence-unit>
</persistence>
I have a stateless EJB which calls entity manager like this:
public FoodServiceBean()
{
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(Persistence.createEntityManagerFactory("semestralka-ejbPU").createEntityManager());
}
Then, there is a REST service class that should list the entities from the database.
#Path("food")
public class FoodResource {
#Context
private UriInfo context;
private FoodServiceInterface service;
/**
* Creates a new instance of FoodResource
*/
public FoodResource() {
try {
InitialContext ic = new InitialContext();
service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean");
} catch (NamingException ex) {...}
}
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("list")
public String getAll() {
List<Food> foods = service.listAllFood();
...
}
}
Unfortunately, once I request the getAll action (visit localhost:8080/semestralka-war/wr/food/list ) I get this exception:
Warning: StandardWrapperValve[cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig]: Servlet.service() for servlet cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig threw exception
javax.naming.NameNotFoundException: dbs not found
Here is a screenshot of the exception screen:
Double check the connection pool name in persistence unit and glassfish server. Also could you update your question with the entities.
I can see that your ejb calling from rest service is wrong. You need to add remote interface name with package path.
Lets say your package path is com.rs.www then your lookup string should be following one :
service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean!com.rs.www.FoodServiceInterface");
Thanks.
Finally, I've found a solution. Problem was in my FoodServiceBean. I was trying to instantiate the facade in the EJB constructor but the EntityManager is injected after the constructor. So here is code of the Bean that helped me solve the issue.
#Stateless
#EJB(beanInterface=FoodServiceInterface.class, name="FoodServiceBean")
public class FoodServiceBean implements FoodServiceInterface {
#PersistenceContext(unitName="testPU")
private EntityManager em;
private FoodFacade facade;
public FoodServiceBean()
{
}
#PostConstruct
public void init() {
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(em);
}
Please note that I changed the name of persistence unit just to be sure there are no typos.
Thanks for the help.
I'm trying to implement a entitymanager-per-conversation pattern on a stateful proprietary web framework with JBoss 4.3.0 and Hibernate 4.3.5. In short, the goal is:
First HTTP request loads entity A with lazy-loading properties from the database
In second request, the lazy-loading properties of entity A are accessible without e.g. creating a new EntityManager and calling e.g. entityManager.merge(entityA).
Entitymanager-per-conversation seems like the perfect choice. Here's my attempt:
public class EntityManagerHolder {
private static ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
private static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myPersistence");
private static ConnectionProvider connectionProvider = new MyConnectionProvider();
public static synchronized EntityManager getEntityManager() {
createEntityManagerIfNeeded();
return entityManager.get();
}
public static synchronized void createEntityManagerIfNeeded() {
if (entityManager.get() == null) {
// Start the conversation
EntityManager newEntityManager = entityManagerFactory.createEntityManager();
entityManager.set(newEntityManager);
newEntityManager.getTransaction().begin();
} else {
// Entitymanager is alive but may have lost its connection
EntityManager existingEntityManager = entityManager.get();
SessionImpl session = existingEntityManager.unwrap(SessionImpl.class);
try {
if (session.connection() == null || session.connection().isClosed()) {
session.reconnect(connectionProvider.getConnection());
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="myEntityManagerFactory">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files from this JAR -->
<property name="hibernate.archive.autodetection" value="class, hbm" />
<!-- Database connection settings: Use framework connections for database connectivity -->
<property name="hibernate.connection.provider_class" value="foo.bar.MyConnectionProvider"/>
</properties>
</persistence-unit>
</persistence>
When a new HTTP request arrives via the framework, I call EntityManagerHolder.createEntityManagerIfNeeded(). On the second HTTP request, the JDBC connection of the EntityManager has closed and the attempt to revive it via session.reconnect() leads to an exception:
java.lang.IllegalStateException: cannot manually reconnect unless Connection was originally supplied
org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.manualReconnect(LogicalConnectionImpl.java:296)
org.hibernate.internal.SessionImpl.reconnect(SessionImpl.java:478)
I realize I'm probably doing things in a very backwards way, but it would be nice to understand how entitymanager-per-conversation should be implemented. I've found the filter-based Hibernate-specific sample implementation of this pattern, but haven't managed to bend it to my needs yet.
Turns out JBoss was closing the connections. Disabling JBoss from closing JDBC connections would have resolved the issue. However, we wanted to avoid keeping a large number of JDBC connections open for long periods of time.
Best solution found so far is to revive the JDBC connection of the EntityManager, provided that the old connection is closed. I wrote a rough implementation:
EntityManagerFactoryAdapter - Used to reconnect an EntityManager to a new JDBC connection
EntityManagerHolder - Keeps one EntityManager per thread.
At the start of each HTTP request, we invoke EntityManagerHolder.initializeEntityManager(freshJDBCConnectionFromFramework). When the state is removed from the server, we invoke EntityManagerHolder.closeEntityManager(). Persistence.xml no longer has the hibernate.connection.provider_class - we're passing in connections manually.
I'm posting this just in case someone encounters a similar issue. This solution is very unorthodox, I'm hoping to replace it with a better one later.
I am using Tomee 7.0 plus as my server. I am using persistence.xml to establish a connection to an online MySQL database using the jdbc:mysql driver. I am using the EntityManager that I receive from the connection, and injecting that into my class, UserManager, where I am running queries.
I am out of solutions why my queries are not hitting my actual table in my database. The error I keep getting is a nullpointer. Is there something wrong with my persistence.xml? Because it doesn't seem to be establishing a full connection...
I am not using Maven, or Spring, or Hibernate. I am in a group project, and I am trying to get this database up and running and would really appreciate any input or idea why my connection isn't established.
Here is the persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="UserService" transaction-type="JTA">
<jta-data-source>userDataSource</jta-data-source>
<class>edu.neumont.pro280.models.User</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://mywebsite.com/trivitup" />
<property name="javax.persistence.jdbc.user" value="trivitup" />
<property name="javax.persistence.jdbc.password" value="password" />
</properties>
</persistence-unit>
</persistence>
I inject the connection to my UserManager and I get null when I print out the currentUser.
This is the UserManager class I use to inject the connection:
#Stateless
#LocalBean
public class UserManager {
#PersistenceContext(unitName = "UserService")
EntityManager em;
public User findUserByUsername(String user) {
System.out.println("User to find is: " + user);
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u WHERE u.username=:user", User.class);
query.setParameter("user", user);
List<User> userList = query.getResultList();
User returnUser = null;
System.out.println("list size: " + userList.size());
if (userList.size() == 1) {
for (User user1 : userList) {
returnUser = user1;
}
}
return returnUser;
}
I use a LoginServlet that will authenticate the user if the user was successfully retrieved. Below I get a null when I print out the currentUser's username.
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username = (String) req.getParameter("username");
String password = (String) req.getParameter("password");
User currentUser = userManager.findUserByUsername(username);
System.out.println("This is currentUser... "
+ currentUser.getUsername());
}
Thank you for any kind of idea or help.
So, this solution is very interesting, and I still do not understand all of it. Everything is completely correct with my persistence.xml, that is the exact data someone would need to connect to a MySQL db, but still won't work. In order to solve this nullpointer issue, I had to extract the resource element from my persistence.xml and extract it into another document, called resources.xml, like so:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<Resource id="userDataSource" type="DataSource">
JdbcDriver com.mysql.jdbc.Driver
JdbcUrl jdbc:mysql://mywebsite.com/trivitup
UserName trivitup
Password password
</Resource>
</resources>
and after that, I had established db connection.
Your error may have something to do with the fact that you provide both jta-data-source and explicit URL properties.
I'm guessing that what happens is that JPA is using the datasource that is bound to userDataSource in JNDI, instead of the datasource specified by the properties inside persistence.xml. You should doublecheck how you're defining the userDataSource data source, and preferably remove the explicit URL/username/password properties.
when Tomee start up, You can see the log of config JPA Persistence Unit. If there wasn't log about that, make sure your META-INF directory at the root class path.
This is my first attempt at Entity beans and I repeatedly get the following error:
java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
I wrote a simple entity beans example using a Netbeans 7.3 and GlassFish 3.1.2.2 Server. It seems there is a problem with my persistance.xml file. However, I am unable to fix this. I read up
JavaEE 6: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
Unable to retrieve EntityManagerFactory for unitName null for simple EJB - see nosferatum answer
But after hours also I have not quite been able to fix this. I am attaching the screenshot of my directory structure and also code for my XML file with the hope that someone can point out the mistake.
persistance.xml : ( Code autogenerated by NetBeans )
<?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="EnterpriseApplication3-ejbPU" transaction-type="JTA">
<jta-data-source>TestDatabase</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
Failing Code :
Declaration :
// This injects the default entity manager factory
#PersistenceUnit
private EntityManagerFactory emf;
Point of Invocation :
EntityManager em = emf.createEntityManager();
Also, a few people seem to do this :
#PersistenceContext(unitName = "myPU")
and have the same name in the persistance.xml. I did a quick search of all my project files and did not come up with the #PersistenceContext annotation. But I added
#PersistenceContext(unitName = "EnterpriseApplication3-ejbPU")
to my code that calls the EntityManagerFactory. But still no success :(
try this one:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnterpriseApplication3-ejbPU");
EntityManager em = emf.createEntityManager();
I'm creating my first JPA application using NetBeans. I'm unable to make the persistence work. The connection to database works well, when I run the application the database tables got created. But when I try to create EntityManagerFactory:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PISProjektPU");
I get:
INFO: javax.persistence.PersistenceException: [PersistenceUnit: PISProjektPU] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:126)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:78)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at cz.vutbr.fit.pis.spravaTechniky.service.TestManager.<init>(TestManager.java:28)
at cz.vutbr.fit.pis.spravaTechniky.service.__EJB31_Generated__TestManager__Intf____Bean__.<init>(Unknown Source)
...
My persistence.xml file looks like this (generated by NetBeans, I didn't change anything):
<?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="PISProjektPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/myslq_spravaTechniky</jta-data-source>
<class>cz.vutbr.fit.pis.spravaTechniky.data.TestEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
</persistence>
and it's located here:
src/conf/persistence.xml
build/web/WEB-INF/classes/META-INF/persistence.xml
I searched the forum and found some tips how to remove this error, but I was unable to make it work. I tried to add these two lines to Manifest.mf:
Meta-Persistence: META-INF/persistence.xml
JPA-PersistenceUnits: PISProjektPU
I tried to move the persistence.xml file to all possible locations. I also added all libraries that seemed like they might be useful, when I go to Properties/Libraries, I see:
Java EE 6 API Library
Hibernate
Java-EE-GlassFish-v3
EclipseLink(JPA 2.0)
EclipseLink-GlassFish-v3
Hibernate JPA
JSF 2.0
Java EE Web 6 API Library
Persistence
I'm sure I'm doing some stupid simple mistake, but after a day trying to make this work I am unable to see where is the problem. To be honest right now I'm just totally confused about where to put which file or how to configure everything, so I'm randomly trying different things. I will be thankful for any advice!
Edit:
Thanks for the suggestion. My test classes actually look like this:
Class TestManager:
#Stateless
public class TestManager {
#PersistenceContext
private EntityManager em;
public void save(TestEntity t) {
em.merge(t);
}
public void remove(TestEntity t) {
em.remove(em.merge(t));
}
public void create(TestEntity t) {
em.persist(t);
}
#SuppressWarnings("unchecked")
public List<TestEntity> findAll() {
return em.createQuery("SELECT t FROM TestEntity t").getResultList();
}
}
Class TestBean:
#Named(value="testBean")
#Dependent
public class TestBean {
#EJB
private TestManager testManager;
/** Creates a new instance of TestBean */
public TestBean() {
}
public List<TestEntity> getEntities() {
return this.testManager.findAll();
}
}
I'm calling the TestBean.getEntities method:
...
<h:dataTable value="#{testBean.entities}" var="entity">
...
This causes the following exception:
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:5119)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5017)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4805)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2004)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1955)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:198)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84)
at $Proxy141.findAll(Unknown Source)
at cz.vutbr.fit.pis.spravaTechniky.service.__EJB31_Generated__TestManager__Intf____Bean__.findAll(Unknown Source)
at cz.vutbr.fit.pis.spravaTechniky.back.TestBean.getEntities(TestBean.java:27)
...
I tried to replace the #PersistenceContext with #EJB, but got javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB.
try to use this one
#EJB
EntityManager em;
em.persist(someobject);
instead of factory, if you need to use factory , i suggest you to repeat steps of setting up the persistance of entities in your IDE
Several things to correct here:
First, you are mixing Hibernate and EclipseLink in the same application (why??) you should just use one of them, choose between Hibernate or EclipseLink as both are implementations of the same standard: JPA (and you will need to choose the JPA API from one of those implementations).
Try to replace the #EJB annotation for a #Inject one. With the stack you are using that one should work.
Using the "dependent pseudo-scope" (by means of the #Dependent annotation) is the same as not establishing a scope at all (no annotation). Remove the #Dependent annotation from your bean class and place there a #RequestScoped (#SessionScoped, #ApplicationScoped or whatever scope your bean should have).
In the end I made JPA work just by using one of the example projects in NetBeans (File > New Project > Samples > Java Web > JSF JPA). I used this as a base for my project. I am not sure what I was doing wrong but at least everything worked fine then. Anyway, thanks for the help!