I have a JSF application that uses Eclipse Persistence Services - 2.1.1.v20100817-r8050, and I sometimes get the following error:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Invalid state, the Connection object is closed.
Error Code: 0
Call: SELECT XXXXX FROM XXXXX
bind => [/Home/Footer/]
Query: ReadAllQuery(name="WWW.find" referenceClass=WWW sql="SELECT XXXXX FROM XXXXX")
I have no idea what is causing it. The exception is thrown in the following function on the "return q.getResultList();" line.
public List<WWW> find(String url) {
}
EntityManager em = getEntityManager();
try {
Query q = em.createNamedQuery("WWW.find");
q.setParameter("url", url);
return q.getResultList();
} finally {
em.close();
}
}
We have SQL Server 2005 and the database isn't down. This is more of a recent thing to consistently happen. Below is the properties that we set in the persistence.xml file. Any comments on what should change in this?
<properties>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="javax.persistence.jdbc.user" value="user"/>
<property name="javax.persistence.jdbc.driver" value="net.sourceforge.jtds.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:jtds:sqlserver://SERVER:1433/DB"/>
<property name="eclipselink.ddl-generation" value="none"/>
<property name="eclipselink.jdbc.timeout" value="20"/>
<property name="eclipselink.jdbc.connections.wait-timeout" value="20"/>
<property name="javax.persistence.query.timeout" value="20"/>
<property name="eclipselink.allow-zero-id" value="true"/>
</properties>
Here is my edited class
public class WWWJpaController {
public WWWWJpaController() {
emf = Persistence.createEntityManagerFactory("properties");
}
public WWWWJpaController(String unitName) {
emf = Persistence.createEntityManagerFactory(unitName);
}
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public List<WWW> find(String url) {
EntityManager em = getEntityManager();
try {
Query q = em.createNamedQuery("WWW.find");
q.setParameter("url", url);
return q.getResultList();
}finally{
em.close();
}
}
}
My guess is your database connection has timed out, or your database is down.
You may need to retry the query, or re-connect your session.
How have you configured your connection pooling and what database are you using?
Maybe your aplication server is not able to reconnect to the database, as BalusC pointed out in his comment, this happens every time the backup's done.
You can make your server reconnect as pointed in this link for Jboss
Related
I'm trying to run a simple web application on which I want run some tests on Jakarta EE 9.1(Full platform). I deployed my application on Glassfish 6.2.5. While I was running some code with jpa implementation this exception is thrown(the persistence provider is EclipseLink 3.0.2):
jakarta.persistence.PersistenceException: Exception [EclipseLink-4002]
(Eclipse Persistence Services - 3.0.2.v202107160933):
org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost:3306;create=true Error Code: 0
The persistence.xml is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="GestoreDB" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>testJPA.ValueBeen</class>
<properties>
<property name="jakarta.persistence.schema-generation.action" value="drop-and-create"/>
<property name="jakarta.persistence.schema-generation.scripts.create-target" value="database-and-scripts"/>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306;create=true"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="myPwd"/>
</properties>
</persistence-unit>
</persistence>
The Entity is(getters and setters omitted):
#Entity
#NamedQuery(name = "ValueBeen.selectTable", query = "select u from ValueBeen u")
public class ValueBeen
{
public ValueBeen(){
}
public ValueBeen(String value)
{
this.value = value;
}
public ValueBeen(int id, String value)
{
this.id = id;
this.value = value;
}
#Id
#GeneratedValue
private int id;
#NotNull
private String value;
...
}
And the WebServlet who perform persistency is:
#WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ValueBeen valueBeen=new ValueBeen("Hello");
//Manager persistence and manager been
EntityManagerFactory managerPersistence = Persistence.createEntityManagerFactory("GestoreDB");
EntityManager entityManager = managerPersistence.createEntityManager();
//Do persistence
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(valueBeen);
transaction.commit();
//close managers
entityManager.close();
managerPersistence.close();
}
}
I put the jdbc connector jar (Mysql connector 8.0.28) in .\glassfish-6.2.5\glassfish\domains\domain1\lib
As you deploy your app to glassfish container then "transaction-type" in persistence.xml i guess should be "JTA", and property "jakarta.persistence.jdbc.url" is invalid because you do not indicate any database / schema name after ":3306". Glassfish documentation provides instructions and examples how to setup global jdbc connections and those limited to only application scope.
Why doesn't it work:
#Test
public void test() {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-pu");
EntityManager entityManager = entityManagerFactory.createEntityManager();
String id = "id";
long value = 1234L;
entityManager.getTransaction().begin();
FancyEntity fancyEntity = new FancyEntity(id);
entityManager.persist(fancyEntity);
int updateCount = entityManager.createQuery("update FancyEntity item set item.value = ?2 where item.id = ?1").setParameter(1, id).setParameter(2, value).executeUpdate();
assertEquals(1, updateCount);
FancyEntity checkResult = entityManager.find(FancyEntity.class, id);
assertEquals(1234L, checkResult.getValue()); // <- this assert fails
entityManager.getTransaction().commit();
}
with
#Entity
public class FancyEntity {
#Id
private String id;
#Column
private long value;
public FancyEntity(String id) {
this.id = id;
this.value = 0;
}
public FancyEntity() {
}
public long getValue() {
return value;
}
}
and
<persistence-unit name="test-pu"
transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.fancypackage.FancyEntity</class>
<properties>
<property name="eclipselink.logging.level" value="SEVERE"/>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem;sql.enforce_strict_size=true;hsqldb.tx=mvcc" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
</properties>
</persistence-unit>
Result is
java.lang.AssertionError:
Expected :1234
Actual :0
It seems there is some cache that is not invalidated by the update query. checkResult and fancyEntity are the same object. Forcing the refresh using entityManager.refresh(checkResult). The weirdest thing is that a select is issued for retrieving checkResult (seen in the eclipselink log), still its result is not taken into account. Same behavior using MySQL rather than HSQL.
Any hint on what could be wrong ?
That is a bulk update statement, As the JPQL language reference notes:
The persistence context is not synchronized with the result of the
bulk update or delete. Caution should be used when executing bulk
update or delete operations because they may result in inconsistencies
between the database and the entities in the active persistence
context. In general, bulk update and delete operations should only be
performed within a separate transaction or at the beginning of a
transaction (before entities have been accessed whose state might be
affected by such operations).
https://docs.oracle.com/html/E24396_01/ejb3_langref.html#ejb3_langref_bulk_ops)
So the behaviour you are seeing makes perfect sense.
I made small rest ws to learn rest. With out using EntityManager its run fine. But when i'm using EntityManager it'll give NPE. I'm using jboss-eap-6.2,EJB 3, JPA. After google that error find out EntityManager is null. How to solve this problem.
#Stateless
#Path("/dili")
public class TestResource {
#PersistenceContext(unitName = "AjaxrestPU")
private EntityManager em;
#GET
#Path("{key}")
#Produces("application/xml")
public Customer getMsg(#PathParam("key") int key) {
Customer cu = em.find(Customer.class, 1);
System.out.println("key " + key);
return cu;
}
//return "okkkk";
}
persistance.xml
<persistence-unit name="AjaxrestPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/tutes</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
Error in boss
13:09:38,862 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default
host].[/Ajaxrest].[org.test.ApplicationConfig]] (http-/127.0.0.1:8080-2) JBWEB0
0236: Servlet.service() for servlet org.test.ApplicationConfig threw exception:
org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationExcep
ion(SynchronousDispatcher.java:365) [resteasy-jaxrs-2.3.7.Final-redhat-2.jar:2.
.7.Final-redhat-2]
After 2 hrs of searching found answer.
Making empty beans.xml in web-inf. That all.
https://netbeans.org/bugzilla/show_bug.cgi?id=231595
I'm trying to create EntityManager in my webapp, but it's failing with:
No suitable driver found for jdbc:postgresql:://localhost/database
However the same persistance unit and the same code for creating EntityManager works when I run it as JavaSE console application (from main() ).
Googling gave me several common problems causing that error:
JDBC url is wrong
Shouldn't be since it works from main
JDBC Driver is not in the class path
I can create a Class object using Class.forName("org.postgresql.Driver"); for the driver so I think it is in the classpath.
Other things I tried:
I thought maybe the driver jar from glassfish/lib and the webapp/WEB-INF/lib are conflicting somehow so I tried with both of them together and separately, no luck.
Recreated a small new webapp hoping the problem will go away, it didn't :-)
Inject #PersistanceUnit - also didn't work, don't know is it the same issue or I didn't use it properly as I'm still learning about injection and EJBs
Thanks
Full error:
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost/database Error Code: 0
Here is the code:
ManagedBean in webapp:
#ManagedBean
public class TestBean {
private String entry;
private String driver;
public String getFromDatabase(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Unit1");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
EntityOne one = new EntityOne();
one.id = 1;
one.entry = "Bla bla";
em.persist(one);
tx.commit();
em.close();
return "done";
}
public String createDriver(){
try {
Class d = Class.forName("org.postgresql.Driver");
driver = d.getName();
} catch (ClassNotFoundException e) {
driver = "Class not found";
return "";
}
return "";
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getEntry() {
return entry;
}
public void setEntry(String entry) {
this.entry = entry;
}
}
Same code working in main:
public class Standalone {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Unit1");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
EntityOne one = new EntityOne();
one.id = 1;
one.entry = "Bla bla";
em.persist(one);
tx.commit();
em.close();
}
}
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="Unit1" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.test.EntityOne</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/database"/>
<property name="javax.persistence.jdbc.user" value="darko"/>
<property name="javax.persistence.jdbc.password" value="sifra"/>
<property name="eclipselink.target-database" value="PostgreSQL"/>
</properties>
</persistence-unit>
Place the posgres jdbc driver into the lib of glassfish. Its something like this.
[glassfish_home]/glassfish/domains/YOUR_DOMAIN/lib/
Also, restart the server after this.
With this 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_1_0.xsd"
version="1.0">
<persistence-unit name="ODP_Server_Test"
transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- <non-jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/ODPServerDataSource)</non-jta-data-source> -->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:unit-testing;create=true" />
<property name="javax.persistence.jdbc.user" value="" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.target-database" value="DERBY" />
</properties>
</persistence-unit>
</persistence>
and a simple test:
public class RepositoryTest {
private static Logger logger = LoggerFactory
.getLogger(RepositoryTest.class);
private static EntityManagerFactory emf;
private EntityManager em;
private RepositoryImpl repo = new RepositoryImpl();
#BeforeClass
public static void setUp() {
try {
logger.info("Starting in-memory DB for unit tests");
#SuppressWarnings("unused")
Class<?> cls = org.apache.derby.jdbc.EmbeddedDriver.class;
DriverManager.getConnection(
"jdbc:derby:memory:unit-testing;create=true").close();
} catch (Exception ex) {
ex.printStackTrace();
fail("Exception during database startup.");
}
try {
logger.info("Building JPA EntityManager for unit tests");
emf = Persistence.createEntityManagerFactory("ODP_Server_Test");
} catch (Exception ex) {
ex.printStackTrace();
fail("Exception during JPA EntityManager instantiation.");
}
}
#AfterClass
public static void tearDown() throws SQLException {
logger.info("Shutting down JPA");
if (emf != null) {
emf.close();
}
try {
DriverManager.getConnection(
"jdbc:derby:memory:unit-testing;drop=true").close();
} catch (SQLException ex) {
if (ex.getSQLState().equals("08006")) {
logger.info("DB shut down");
} else {
throw ex;
}
}
fail("DB didn't shut down");
}
#Before
public void setEM() {
em = emf.createEntityManager();
repo.setEntityManager(em);
}
#After
public void flushEM() {
if (em != null) {
em.flush();
em.close();
em = null;
}
}
#Test
public void noBlocksInEmptyDB() {
assertThat(repo.findFunBlock(1), is((FunctionalBlock) null));
}
}
I get
[EL Warning]: 2012-04-17 15:08:18.476--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
After replacing <exclude-unlisted-classes>false</exclude-unlisted-classes> with a lot of <class> elements, the problem can be fixed, but I'd prefer not to have to remember to edit persistence.xml every time I need to add a new entity or remove an old one. Why doesn't the version with <exclude-unlisted-classes> work?
I had faced similar situation
If I generate JPA metamodel, copy paste it in correct pacakge and check it in to svn, and disable metamodel generation, all junit tests were fine
if i generate metamodel with every build, at junit time - embedded glassfish will find all ejb and metamodel fine, but non ejb junit will fail
I had to do this in my src/test/resources/META-INF/persistence.xml
<persistence-unit name="test-xxx" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<jar-file>file:../classes</jar-file>
<shared-cache-mode>ALL</shared-cache-mode>
<properties>
<property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform"/>
<property name="eclipselink.logging.timestamp" value="true"/>
<property name="eclipselink.logging.thread" value="true"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.logger" value="JavaLogger"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#localhost:1521:xxx"/>
<property name="javax.persistence.jdbc.password" value="xxx"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.user" value="xxx"/>
</properties>
</persistence-unit>