How to avoid stalled DB connections with TomEE's JDBC connection pool? - java

I'm creating a JSF web app on TomEE1.7.2 (over tomcat7, javaEE6).
I have JDBC to mysql5.6.23 connection setting which look like below,
and it is working just good, for only some hours.
My data access super class:
public class BaseDao {
#javax.ejb.EJB
MyEnvironmentService env;
#javax.persistence.PersistenceContext(unitName = "persistence-unit-stg")
protected javax.persistence.EntityManager em_stg;
#javax.persistence.PersistenceContext(unitName = "persistence-unit-prd")
protected javax.persistence.EntityManager em_prd;
protected javax.persistence.EntityManager em;
#javax.annotation.PostConstruct
private void init(){
switch (env.getName()){
case "stg":
em = em_stg;
break;
case "prd":
em = em_prd;
break;
default:
throw new RuntimeException("Oh no!");
}
}
}
My data access class:
#javax.ejb.Stateless
public class MyDao extends BaseDao{
public MyEntity find(Object id) {
return em.find(MyEntity.class, id);
}
}
My META-INF/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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistence-unit-stg" transaction-type="JTA">
<jta-data-source>mysql-jdbc-jta-resource-stg</jta-data-source>
</persistence-unit>
<!-- almost same persistence-unit for prd -->
</persistence>
My WEB-INF/resource.xml:
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<Resource id="mysql-jdbc-jta-resource-stg" type="javax.sql.DataSource">
JdbcDriver com.mysql.jdbc.Driver
JdbcUrl jdbc:mysql://db-stg.bar.someRegion.rds.amazonaws.com/someDBname
UserName username
password password
jtaManaged true
</Resource>
<!-- almost same Resource for prd -->
</resources>
I have 2 problems that I want to solve:
1.
When I start my web app on staging environment, leave it, and mysql "wait_timeout" comes, my web application gets
javax.transaction.RollbackException: Transaction is marked for rollback
and CANNOT reconnect to mysql again forever.
I've already tried some JDBC's
autoreconnect=true or autoreconnectForPool=true
things, did NOT work either, and I feel like it's not the best thing to do, in the first place (feature already deprecated?) .
2.
When I start my web app, I see exactly 3 connections connected to mysql,
and everytime, ONLY 1 of the connection is seem to be used and extends its timeout,
but other 2 are never used and killed just at the "wait_timeout".
I tried "initialSize 10", and it comes with 15 connections,
and again, ONLY 1 of the connection is used.
I guess there is a really simple solution for them,
because it says:
Internally, from TomEE 1.5.0, JDBC pools are managed via Tomcat-pool.
in this page http://tomee.apache.org/common-datasource-configurations.html
Well yes, I DO want to use this Tomcat JDBC pool ( or something alternative is fine.), it doesn't seem to be enabled.
May be I'm missing some xml settings or jar or whatever, but I have no idea.
please help me out.

I'm successfully using a resources.xml in my WEB-INF folder similar to this one in of my production projects:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<Resource id="mysql-jdbc-jta-resource-stg" type="javax.sql.DataSource">
JtaManaged = true
DataSourceCreator = tomcat
validationQuery = SELECT 1
initialSize = 2
removeAbandoned = true
removeAbandonedTimeout = 120
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://db-stg.bar.someRegion.rds.amazonaws.com/someDBname
username = your-username
password = your-pw
</Resource>
</resources>
One important difference is to use DataSourceCreator = tomcat. This ensures that TomEE creates a pool which takes care for connection validation ("SELECT 1") and removes stalled/outdated connections, thus freeing up resources in the background.
By contrast, the DataSourceCreator = dbpc (which is default when not set: "Default provided pools are DBCP...") behaved as you described/experienced it (timeouts,...). Check the related documentation for further differences.
Also note, that = is used in my working configuration. I discovered that in previous TomEE releases it seemed to work without =. However, I would recommend to configure with = consistently when your target application server is TomEE 1.7.2 or higher.
Further details on this can also be found in the DataSource Configuration page.
Hope it helps.

Related

java.lang.ClassCastException,Getting Entitymanager Via JNDI Lookup

I am new to JPA and developing a webapp(J2EE) where the webapp is in Tomcat so I can't use #PersistenceContext. I decided to use a Helper class and everything was going fine. Then I decided to implement JNDI for connection pooling and I managed to get Datasource.
The Helper Class looks like the following:
try {
Context initCtx = new InitialContext();
entityManager = //class cast exception
(EntityManager)initCtx.lookup(
"java:/comp/env/jdbc/LCDS"
);
DataSource ds= (DataSource)initCtx.lookup(
"java:/comp/env/jdbc/LCDS"
);
System.out.println(ds.getConnection()+"Cool");
//jdbc:mysql://localhost:3306/XXXXXXX, UserName=root#localhost, MySQL-AB JDBC DriverCool
emf=(EntityManagerFactory) source.getConnection(); //class cast exception
emf = Persistence.createEntityManagerFactory("XXXX"); //working version
}
The error is:
ava.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.BasicDataSource cannot be cast to javax.persistence.EntityManager
I don't know where I am getting wrong. I am not able to get EntityManagerFactory or EntityManager via JNDI lookup. I tried #Resource(name="jdbc/LCDS") and #PersistenceUnit(name="jdbc/LCDS").
To use a JNDI datasource in JPA, this should be specified in the persistence.xml, something like:
<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">
<persistence-unit name="..." transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:/comp/env/jdbc/LCDS</non-jta-data-source>
...
Then you just have to create your EntityManagerFactory via Persistence#createEntityManagerFactory(String). If you want to recycle the EntityManagerFactory, this should be done outside of JNDI (e.g. as a ServletContext attribute). This is because Tomcat is not a Java EE server, only a servlet container: he is not able to inject the persistence unit.
UPDATE
JNDI access to persistence unit is not possible due to Tomcat limitations. See JPA Tomcat limitations. You will have to use emf = Persistence.createEntityManagerFactory("UNIT NAME").
Sorry for misleading answer. I've tested that on WebSphere Liberty, didn't have Tomcat at hand.
If you need that functionality check WebSphere Liberty, which is as fast and lightweight as Tomcat, but is fully Java EE Web profile compliant. It has lots of useful features like JPA, EJBLite, JAX-RS already available if needed, without fighting with additional libraries configuration.
UPDATE END
I've checked on WebSphere Liberty, you need to create reference to lookup your persistence unit via JNDI. You have two options to create that:
Use annotation at the class level
In any of your servlets you need to define annotation using the follownig:
#PersistenceUnit(name="JPATestRef", unitName="UnitName")
public class JPATester extends HttpServlet {
...
Use entry in web.xml
<persistence-unit-ref>
<persistence-unit-ref-name>JPATestRef</persistence-unit-ref-name>
<persistence-unit-name>UnitName</persistence-unit-name>
</persistence-unit-ref>
Then you access it using the following code:
try {
InitialContext ctx = new InitialContext();
System.out.println("looking EntityManagerFactory:");
EntityManagerFactory emf2 = (EntityManagerFactory) ctx.lookup("java:comp/env/JPATestRef");
System.out.println("emf:2" + emf2);
} catch (NamingException e) {

JPA 2 (Hibernate) persistence context per conversation - closed connection

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.

Using persistence.xml to connect to MySQL database. Why is EntityManager query returning null?

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.

How to get jpa datasource properties from Entity Manager

Hi everybody
I was wondering if it's possible to get database connection properties through entity manager.
My persistence.xml looks like this
<persistence ...>
<persistence-unit name="default" transaction-type="JTA">
<jta-data-source>DatasourceForTestSystem</jta-data-source>
<class> some.package.and.some.Class </class>
...
</persistence-unit>
</persistence>
I want something like
String host = em.getSomeFunction().getProperties().get("server");
String database = em.getSomeFunction().getProperties().get("database");
or
String url = em.getSomeFunction().getConnectionPool().getURL();
where url is something like jdbc:oracle:thin:#1.2.3.4:5678:database.
I'm using JDeveloper 12c with EclipseLink, an Oracle database and NO Hibernate.
Does somebody know how to get information about the connection properties?
Kind regards,
Stefi
-- UPDATE --
#Kostja: thx again for your help but as I mentioned in my post I do not use Hibernate at all.
I already tried to use the Connection.class like this
java.sql.Connection conn = em.unwrap(java.sql.Connection.class);
from here. I always got a NPE for the Connection as well as for getSession() in this statement
((JNDIConnector)em.unwrap(JpaEntityManager.class)
.getSession().getLogin().getConnector()).getName();
from here.
I'm quiet confused why any of these solutions work for me. Maybe I'm missing something :-(
The farthest you can go with JPA is to query the properties of the EntityManagerFactory or the Connection. The list of available properties varies between providers and between different version of a single provider.
Access the properties of the EMF like this:
Map<String,Object> props = emf.getProperties();
Getting your hands on the Connection is a bit more involved and depends on the JPA implementation. This could work for Hibernate, courtesy #Augusto:
cast the EntityManagerFactory to HibernateEntityManagerFactory,
call getSessionFactory() and cast it to SessionFactoryImpl, call getConnectionProvider()
connectionProvder.getConnection();

Correct usage of JPA in jsp application

I'm trying to develop a simple JSP based web application with JPA and would like to know the correct usage for developing one.
In my sample application I have two JSP pages and a simple Java class to perform database operations. Both the JSP files use this Java class to perform DB operations.
I've annotated this class with #Stateless and injected an Entity manager as follows:
#PersistenceContext(unitName = "myjpa")
EntityManager em;
In my persistence.xml I've set the following property:
<property
name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"
/>
I'm calling the class in JSP using JNDI (as the class is annotated for a stateless session bean) as follows:
InitialContext ic = new InitialContext();
Sample sample = (Sample) ic.lookup("java:app/" + application.getContextPath() + "/Sample");
I'm facing the following scenarios:
When I try to use a transaction em.getTransaction().begin()/commit() for insert and update, it says can not use transaction with JTA case.
So in the constructor code of my Java class I use the following code:
Properties properties = new Properties();
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
emf = Persistence.createEntityManagerFactory("myjpa",properties);
em = emf.createEntityManager();
I tried to use transactions like em.getTransaction().begin()/commit().
But in this case the pages become very slow after 2-3 database update and load operations. Though I'm not getting any exception. Overall in my table I'm having less than 25 records.
To me it seems as if it is waiting internally for some operation to complete.
At the same time I also feel that the way I'm using JPA is wrong and hence soliciting advice for the correct approach for doing even simple web apps with JSP and JPA.
While I'm still exploring Java EE, in case you have any specific reference for such cases I'll like to read and look them too.
You should always strive to use JTA transactions which means the container will handle the transaction demarcations. In your case if you want to handle transactions by your self, you need to define it as a bean managed transaction. So in your EJB class, after the #Stateless annoattions, you should define the following annotation;
#TransactionManagement(TransactionManagementType.BEAN)
The usual best practice is to let the container handle the transactions, unless there is some explicit reason for you to use Bean managed transactions.
At the same time I also feel that the way I'm using JPA is wrong
Your usage indeed seems wrong. If you're using a (stateless) session bean you do not have to fiddle with em.getTransaction().begin()/commit() and you definitely don't have to use code such as Persistence.createEntityManagerFactory.
You also don't have to set the property org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform.
A session bean automatically manages the transaction for you, and within a Java EE AS (such as JBoss AS) you don't have to configure any transaction manager or similar things.
An example:
#Stateless
public class UserDAO {
#PersistenceContext
private EntityManager entityManager;
public void add(User user) {
entityManager.persist(user);
}
}
As for the persistence.xml file, something like the following should be enough to get started:
<?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="somePU">
<jta-data-source>java:app/someDS</jta-data-source>
</persistence-unit>
</persistence>
Some more examples:
http://jdevelopment.nl/sample-crud-app-with-jsf-and-richfaces
http://arjan-tijms.omnifaces.org/2011/08/minimal-3-tier-java-ee-app-without-any.html

Categories