Migrating to Hibernate 5 - java

I am migrating an application from Hibernate 4.3 to Hibernate 5.0.1-Final
I use ImplicitNamingStrategyComponentPathImpl as my hibernate.implicit_naming_strategy with Postgres 9.4.4 and my company uses hibernate.hbm2ddl.auto = update for deployment ( I know it is a bad practice but cant help it)
While the session factory initializes, it throws the below error. Apparently the generated alias is too long for Postgres. How do we go about this situation? I have tried assigning #Table(name=..) annotation to work around this it but it is getting worse as every relationship from that point gets screwd.
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [create table public.ReferenceDocumentVersion_ReferenceDocumentSourceFilesStoreDescriptor (ReferenceDocumentVersion_unid uuid not null, sourceFilesStore_filesDescriptorMap_unid uuid not null, filesDescriptorMap_KEY text not null, primary key (ReferenceDocumentVersion_unid, filesDescriptorMap_KEY))]
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:371)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:360)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.createTable(SchemaMigratorImpl.java:181)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:134)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:59)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:129)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:97)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:481)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:802)
... 29 more
Caused by: org.postgresql.util.PSQLException: ERROR: relation "referencedocumentversion_referencedocumentsourcefilesstoredescr" already exists
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:618)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:454)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:382)
at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at net.bull.javamelody.JdbcWrapper.doExecute(JdbcWrapper.java:404)
at net.bull.javamelody.JdbcWrapper$StatementInvocationHandler.invoke(JdbcWrapper.java:129)
at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:286)
at com.sun.proxy.$Proxy93.executeUpdate(Unknown Source)
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56)
... 39 more

I have addressed the situation with a custom ImplicitNamingStrategy that truncates Hibernate generated identifiers to 64 chars (MAX length for Postgres).
Previous versions of Hibernate(4.x) have encountered the same error but they just ignores it and proceeds with initializing the SessionFactory. However, Hibernate 5.x has a new boot strap API which throws a SchemaManagementException in such cases and aborts. Hibernate logs from my test scenarios are pasted below for reference.
Hibernate 4.X
INFO: HHH000396: Updating schema
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
ERROR: HHH000388: Unsuccessful: create table ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres (unid uuid not null, path text, primary key (unid))
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
ERROR: ERROR: relation "referencedocumentversionentitywithareallyreallyreallylongnamebe" already exists
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
Hibernate 5.0.2.Final
Oct 04, 2015 1:39:16 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Oct 04, 2015 1:39:16 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:39:16 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.813 sec <<< FAILURE!
testApp(org.foobar.AppTest) Time elapsed: 0.788 sec <<< ERROR!
javax.persistence.PersistenceException: [PersistenceUnit: org.foobar.persistence.default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:877)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:805)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at org.foobar.AppTest.testApp(AppTest.java:18)
Solution
Custom ImplicitNamingStrategy
package org.foobar.persistence;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl;
import org.hibernate.boot.spi.MetadataBuildingContext;
public class PGConstrainedImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl {
private static final int POSTGRES_IDENTIFIER_MAXLENGTH = 63;
public static final PGConstrainedImplicitNamingStrategy INSTANCE = new PGConstrainedImplicitNamingStrategy();
public PGConstrainedImplicitNamingStrategy() {
}
#Override
protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
return buildingContext.getMetadataCollector()
.getDatabase()
.getJdbcEnvironment()
.getIdentifierHelper()
.toIdentifier( stringForm.substring( 0, Math.min( POSTGRES_IDENTIFIER_MAXLENGTH, stringForm.length() ) ) );
}}
persistence.xml
<properties>
<property name="hibernate.implicit_naming_strategy" value="org.foobar.persistence.PGConstrainedImplicitNamingStrategy"/>
</properties>
This is not a scalable solution at all but helps to keep the show running. The permanent solution would be to explicitly supply identifiers so that hibernate does not generate really long identifiers. - see the answer written by maaartinus

try to follow the Migration guide in Hibernate Documentation in this link
https://github.com/hibernate/hibernate-orm/blob/5.0/migration-guide.adoc

The OP's solution may lead to collision (that's why he calls it not scalable, right?). Explicitly supplying all identifiers sound like a terrible idea to me. I'd suggest one of the following
provide a Map<String, String> mapping all overlong names to something shorter
shorten all overlong names to POSTGRES_IDENTIFIER_MAXLENGTH - N and append N characters generated from the hash of the cut away part, so the probability of collisions gets minimized
Use some identifier abbreviating function like {"Reference" -> "Ref", "Document" -> "Doc", ...} and apply it to your identifiers before they get processed, so that you get RefDocVersion_RefDocSourceFileDescr... instead of referencedocumentversion_referencedocumentsourcefilesstoredescr....
Consider using abbreviated names in you code itself. This is often advised against, as it easily leads to incomprehensible non-sense, but IMHO it increases readability when used right (use only a couple of abbreviations and use them systematically; provide a list of them).

Related

How to map a collection of entities, inside an entity, using Hibernate?

I'm developing a distributed software system and I'm trying to use the Hibernate framework for the first time. One of my classes (which is a mapped Entity) has an ArrayList<> containing objects of another class (which is also an Entity).
Ex:
I have an Event class, which is a #MappedSuperclass.
I have a CorporateEvent class, which is an entity, that inherits from Event.
I have a Task class, which is also an Entity.
My CorporateEvent class has an attribute called "tasks", which is an ArrayList.
How do I map this correctly to the database so that there's a table called Event and a table called Task, which has a key connecting them to eachother?
I'm using the newest Hibernate version and the database is on a PostgreSQL server. The dialect in Hibernate is set to PostgreSQL.
We've tried using #ElementCollection and #CollectionTable, but we're getting some weird NullPointerExceptions. It might have something to do with the inheritance aspect of the code.
Here is the 3 classes in question:
Event Class:
#MappedSuperclass
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Event {
#Column(name="title")
private String title;
#Column(name="location")
private String location;
#Column(name="date")
private String date;
CorporateEvent Class:
#Entity
#Table(name="corporate_event")
public class CorporateEvent extends Event {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_generator")
#SequenceGenerator(name = "id_generator", sequenceName = "corporate_event_id_seq", allocationSize = 1)
#Column(name = "id", updatable = false, nullable = false)
private int id;
#ElementCollection
private ArrayList<Task> tasks;
#Column(name="expenses")
private String expenses;
Task Class:
#Entity
#Table(name="task")
public class Task {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_generator")
#SequenceGenerator(name="id_generator", sequenceName = "task_task_id_seq", allocationSize=1)
#Column(name="task_id", updatable = false, nullable = false)
private int id;
#Column(name="name")
private String taskName;
#Column(name="description")
private String description;
I expect the output to be that a CorporateEvent object is saved to the database and the Task objects in its ArrayList are each saved in the Task table with a CorporateEvent ID that connects them to the right event.
What I instead get is a NullPointerException on the line where I try to save the CorporateEvent object using Hibernate. This is the error message:
------------------------------------------------------------------------
Building Eventer 1.0-SNAPSHOT
------------------------------------------------------------------------
--- maven-resources-plugin:2.5:resources (default-resources) # Eventer ---
[debug] execute contextualize
Using 'UTF-8' encoding to copy filtered resources.
Copying 11 resources
--- maven-compiler-plugin:3.6.1:compile (default-compile) # Eventer ---
Nothing to compile - all classes are up to date
--- exec-maven-plugin:1.2.1:exec (default-cli) # Eventer ---
Nov 08, 2019 5:31:30 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.4.8.Final}
Nov 08, 2019 5:31:30 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
Nov 08, 2019 5:31:31 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Nov 08, 2019 5:31:31 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.postgresql.Driver] at URL [jdbc:postgresql://tek-mmmi-db0a.tek.c.sdu.dk:5432/si3_2019_group_5_db]
Nov 08, 2019 5:31:31 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=si3_2019_group_5, password=****}
Nov 08, 2019 5:31:31 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Nov 08, 2019 5:31:31 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 1 (min=1)
Nov 08, 2019 5:31:31 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Nov 08, 2019 5:31:35 PM org.hibernate.cfg.AnnotationBinder bindClass
WARN: HHH000503: A class should not be annotated with both #Inheritance and #MappedSuperclass. #Inheritance will be ignored for: com.mycompany.domain.event.Event.
Nov 08, 2019 5:31:35 PM org.hibernate.boot.internal.InFlightMetadataCollectorImpl addIdentifierGenerator
WARN: HHH000069: Duplicate generator name id_generator
Exception in thread "main" java.lang.NullPointerException
at com.mycompany.repositories.EventRepository.saveCorporateEvent(EventRepository.java:51)
at com.mycompany.eventer.Eventer.main(Eventer.java:42)
------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
Total time: 7.007s
Finished at: Fri Nov 08 17:31:35 CET 2019
Final Memory: 9M/100M
------------------------------------------------------------------------
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default-cli) on project Eventer: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]
To see the full stack trace of the errors, re-run Maven with the -e switch.
Re-run Maven using the -X switch to enable full debug logging.
The line it complains about is "session.close();" in this method:
public int saveCorporateEvent(CorporateEvent corporateEvent) {
try {
session = ConnectRepository.factory.getCurrentSession();
session.beginTransaction();
session.save(corporateEvent);
session.getTransaction().commit();
return corporateEvent.getId();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
return 0;
}
And if I remove the session.close(); I get the following annotation error, which I don't understand, since an ArrayList should be supported?:
(The beginning is the same, so I'm only pasting the difference in)
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mycompany.repositories.EventRepository.saveCorporateEvent(EventRepository.java:42)
at com.mycompany.eventer.Eventer.main(Eventer.java:42)
Caused by: org.hibernate.AnnotationException: java.util.ArrayList collection type not supported for property: com.mycompany.domain.event.CorporateEvent.tasks
at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:317)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1939)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:975)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:802)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:473)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:84)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:689)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at com.mycompany.repositories.ConnectRepository.<clinit>(ConnectRepository.java:27)
... 2 more
------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
Total time: 11.877s
Finished at: Fri Nov 08 17:44:27 CET 2019
Final Memory: 19M/208M
------------------------------------------------------------------------
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default-cli) on project Eventer: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]
To see the full stack trace of the errors, re-run Maven with the -e switch.
Re-run Maven using the -X switch to enable full debug logging.
UPDATE:
Now it's somewhat working. But a new problem has appeared. As you can see below, hibernate only inserts into the CorporateEvent table, not the task table.
------------------------------------------------------------------------
Building Eventer 1.0-SNAPSHOT
------------------------------------------------------------------------
--- maven-resources-plugin:2.5:resources (default-resources) # Eventer ---
[debug] execute contextualize
Using 'UTF-8' encoding to copy filtered resources.
Copying 11 resources
--- maven-compiler-plugin:3.6.1:compile (default-compile) # Eventer ---
Nothing to compile - all classes are up to date
--- exec-maven-plugin:1.2.1:exec (default-cli) # Eventer ---
Nov 10, 2019 12:15:21 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.4.8.Final}
Nov 10, 2019 12:15:21 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
Nov 10, 2019 12:15:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Nov 10, 2019 12:15:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.postgresql.Driver] at URL [jdbc:postgresql://tek-mmmi-db0a.tek.c.sdu.dk:5432/si3_2019_group_5_db]
Nov 10, 2019 12:15:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=si3_2019_group_5, password=****}
Nov 10, 2019 12:15:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Nov 10, 2019 12:15:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 1 (min=1)
Nov 10, 2019 12:15:22 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Nov 10, 2019 12:15:26 PM org.hibernate.cfg.AnnotationBinder bindClass
WARN: HHH000503: A class should not be annotated with both #Inheritance and #MappedSuperclass. #Inheritance will be ignored for: com.mycompany.domain.event.Event.
Nov 10, 2019 12:15:26 PM org.hibernate.boot.internal.InFlightMetadataCollectorImpl addIdentifierGenerator
WARN: HHH000069: Duplicate generator name id_generator
Nov 10, 2019 12:15:26 PM org.hibernate.boot.internal.InFlightMetadataCollectorImpl addIdentifierGenerator
WARN: HHH000069: Duplicate generator name id_generator
Hibernate: select nextval ('corporate_event_id_seq')
Hibernate: insert into corporate_event (date, description, location, max_participants, title, expenses, corporate_id) values (?, ?, ?, ?, ?, ?, ?)
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 9.780s
Finished at: Sun Nov 10 12:15:28 CET 2019
Final Memory: 9M/100M
------------------------------------------------------------------------
These are the changes I made using your help:
CorporateEvent class:
#OneToMany(cascade=CascadeType.ALL, mappedBy="corporateEvent")
private List<Task> tasks;
Task class:
#ManyToOne
#JoinColumn(name="corporate_id")
private CorporateEvent corporateEvent;
The code runs successfully, but it will not map the data to the Task table in my database. This is the test (main) code:
public static void main(String[] args) {
ArrayList<Task> arrTasks = new ArrayList<>();
arrTasks.add(new Task("task1", "taskDes1"));
arrTasks.add(new Task("task2", "taskDes2"));
arrTasks.add(new Task("task3", "taskDes3"));
User user = new User("alex", "tholle", "sdu", "software engineering", "at#gmail.com", 70111213, "alexuser", "alexpass", new Date(), true, "student", "e2R213");
Meetup meetup = new Meetup(user.getUserName(), "meetup at the pub", "old irish", new Date().toString(), "det bliver fed", 10);
Task task = new Task("Cleaning", "Do some cleaing please");
CorporateEvent corporateEvent = new CorporateEvent(null, arrTasks, "Tinderbox", "forest", new Date().toString(), "edm music festival", 5000);
for (Task t : arrTasks) {
t.setCorporateEvent(corporateEvent);
}
EventRepository eventRepo = new EventRepository();
eventRepo.saveCorporateEvent(corporateEvent);
The database has the following tables regarding this issue:
create table task
(
task_id serial not null
constraint task_pk
primary key,
name varchar,
description varchar(1000),
corporate_id integer
constraint corporate_id
references corporate_event
on update cascade on delete cascade
);
alter table task
owner to si3_2019_group_5;
create unique index task_task_id_uindex
on task (task_id);
create table corporate_event
(
title varchar,
date varchar(1000),
location varchar,
description varchar,
max_participants integer,
expenses varchar(2000),
corporate_id serial not null
constraint corporate_event_pk
primary key,
tasks varchar(4000)
);
alter table corporate_event
owner to si3_2019_group_5;
create unique index corporate_event_id_uindex
on corporate_event (corporate_id);
Your error is likely due to your usage of the #ElementCollection annotation without a class that is annotated with #Embeddable. I would use a OneToMany annotation implementation instead.
Your CorporateEvent class:
#OneToMany(mappedBy="corporate_event")
private List<Task> tasks;
Your Task class:
#ManyToOne
#JoinColumn(name="corporate_event_id")
private CorporateEvent corporateEvent;

Apache Cayenne: NullPointerException when commitChanges

I'm trying commitChanges, but catch java.lang.NullPointerException. log:
...
INFO: --- transaction started.
авг 04, 2015 12:33:59 PM org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy processSchemaUpdate
INFO: Full or partial schema detected, skipping tables creation
авг 04, 2015 12:33:59 PM org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = 'ARTIST'
авг 04, 2015 12:33:59 PM org.apache.cayenne.log.CommonsJdbcEventLogger logSelectCount
INFO: === returned 1 row. - took 16 ms.
авг 04, 2015 12:33:59 PM org.apache.cayenne.log.CommonsJdbcEventLogger logQueryError
INFO: *** error.
java.lang.NullPointerException
at com.relx.jdbc.jdbc2.LinterStatementImpl.getUpdateCount(LinterStatementImpl.java:419)
at org.apache.cayenne.access.jdbc.SQLTemplateAction.execute(SQLTemplateAction.java:190)
at org.apache.cayenne.access.jdbc.SQLTemplateAction.performAction(SQLTemplateAction.java:124)
at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:280)
at org.apache.cayenne.dba.JdbcPkGenerator.longPkFromDatabase(JdbcPkGenerator.java:310)
at org.apache.cayenne.dba.JdbcPkGenerator.generatePk(JdbcPkGenerator.java:268)
at org.apache.cayenne.access.DataDomainInsertBucket.createPermIds(DataDomainInsertBucket.java:171)
at org.apache.cayenne.access.DataDomainInsertBucket.appendQueriesInternal(DataDomainInsertBucket.java:76)
at org.apache.cayenne.access.DataDomainSyncBucket.appendQueries(DataDomainSyncBucket.java:78)
at org.apache.cayenne.access.DataDomainFlushAction.preprocess(DataDomainFlushAction.java:188)
at org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:144)
at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:853)
at org.apache.cayenne.access.DataDomain$2.transform(DataDomain.java:817)
at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:877)
at org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:814)
at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:1031)
at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:785)
at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:817)
at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:756)
at CayenneTest2.main(CayenneTest2.java:61)
Table AUTO_PK_SUPPORT was created and filled Apache Cayenne.
Why throw the Exception?
From the stack trace you are working with Cayenne v. 3.1. The code in question is here. Cayenne SQLTemplateAction checks whether the result of the query is a ResultSet and with the answer being "no", assumes the result is an update count. So it tries to read the update count on line 190:
int updateCount = statement.getUpdateCount();
Somehow the underlying statement object (LinterStatementImpl) is not happy about that. I don't have access to source code of the Linter DB driver, so I can't say what exactly is wrong, but the driver is not behaving the way Cayenne expects it to.
Perhaps Linter is special enough to warrant its own Cayenne DbAdapter (??) Feel free to join Cayenne dev mailing list to discuss what it takes to write one.

Spring Tomcat C3P0PooledConnectionPoolManager creates a memory leak [duplicate]

I configured tomcat to work with a different external open source.
However, after the tomcat is running for a few minutes I get:
SEVERE: The web application [/MyProject] created a ThreadLocal with
key of type [java.lang.ThreadLocal] (value
[java.lang.ThreadLocal#1b3f02f]) and a value of type
[org.apache.axis.MessageContext] (value
[org.apache.axis.MessageContext#5dbd4e]) but failed to remove it when
the web application was stopped. This is very likely to create a
memory leak.
What could cause it?
Where do I have to look? Could it be datapooling on Tomcat?
And what does it mean Threads in Tomcat?
EDITED
Here is my full trace. The application seems to reloads its context while it's still running - and I don't know why!
Mar 13, 2011 10:56:12 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading this Context has started
Mar 13, 2011 10:56:12 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:13 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:14 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated
Mar 13, 2011 10:56:14 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/MyProject] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/MyProject] registered the JBDC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioSocketAcceptor-1] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-1] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-4] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [bitronix-disk-force-batcher] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [bitronix-scheduler] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-7] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/MyProject] appears to have started a thread named [NioProcessor-2] but has failed to stop it. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#1b5a8e1]) and a value of type [org.mvel2.debug.DebuggerContext] (value [org.mvel2.debug.DebuggerContext#16259fd]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder#84b0b4]) and a value of type [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl#16d2cfa]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [null] (value [com.sun.faces.util.Util$1#16bbac9]) and a value of type [java.util.HashMap] (value [{com.sun.faces.patternCache={ = }}]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#1b3f02f]) and a value of type [org.apache.axis.MessageContext] (value [org.apache.axis.MessageContext#5dbd4e]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder#84b0b4]) and a value of type [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl#378584]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [org.springframework.core.NamedThreadLocal] (value [Transactional resources]) and a value of type [java.util.HashMap] (value [{org.hibernate.impl.SessionFactoryImpl#ccc27b=org.springframework.orm.hibernate3.SessionHolder#4f6ada}]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Mar 13, 2011 10:56:15 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: The web application [/MyProject] created a ThreadLocal with key of type [null] (value [com.sun.faces.application.ApplicationAssociate$1#1f01fcf]) and a value of type [com.sun.faces.application.ApplicationAssociate] (value [com.sun.faces.application.ApplicationAssociate#1b85528]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
2011-03-13 22:57:27,734 ERROR ( ContextLoader.java:220) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [applicationContext-hibernate.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext-hibernate.xml]: Invocation of init method failed; nested exception is java.lang.OutOfMemoryError: Java heap space
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
The message is actually pretty clear: something creates a ThreadLocal with value of type org.apache.axis.MessageContext - this is a great hint. It most likely means that Apache Axis framework forgot/failed to cleanup after itself. The same problem occurred for instance in Logback. You shouldn't bother much, but reporting a bug to Axis team might be a good idea.
Tomcat reports this error because the ThreadLocals are created per HTTP worker threads. Your application is undeployed but HTTP threads remain - and these ThreadLocals as well. This may lead to memory leaks (org.apache.axis.MessageContext can't be unloaded) and some issues when these threads are reused in the future.
For details see: http://wiki.apache.org/tomcat/MemoryLeakProtection
I added the following to #PreDestroy method in my CDI #ApplicationScoped bean, and when I shutdown TomEE 1.6.0 (tomcat7.0.39, as of today), it clears the thread locals.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pf;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* #author Administrator
*
* google-gson issue # 402: Memory Leak in web application; comment # 25
* https://code.google.com/p/google-gson/issues/detail?id=402
*/
public class ThreadLocalImmolater {
final Logger logger = LoggerFactory.getLogger(ThreadLocalImmolater.class);
Boolean debug;
public ThreadLocalImmolater() {
debug = true;
}
public Integer immolate() {
int count = 0;
try {
final Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
final Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocalsField.setAccessible(true);
for (final Thread thread : Thread.getAllStackTraces().keySet()) {
count += clear(threadLocalsField.get(thread));
count += clear(inheritableThreadLocalsField.get(thread));
}
logger.info("immolated " + count + " values in ThreadLocals");
} catch (Exception e) {
throw new Error("ThreadLocalImmolater.immolate()", e);
}
return count;
}
private int clear(final Object threadLocalMap) throws Exception {
if (threadLocalMap == null)
return 0;
int count = 0;
final Field tableField = threadLocalMap.getClass().getDeclaredField("table");
tableField.setAccessible(true);
final Object table = tableField.get(threadLocalMap);
for (int i = 0, length = Array.getLength(table); i < length; ++i) {
final Object entry = Array.get(table, i);
if (entry != null) {
final Object threadLocal = ((WeakReference)entry).get();
if (threadLocal != null) {
log(i, threadLocal);
Array.set(table, i, null);
++count;
}
}
}
return count;
}
private void log(int i, final Object threadLocal) {
if (!debug) {
return;
}
if (threadLocal.getClass() != null &&
threadLocal.getClass().getEnclosingClass() != null &&
threadLocal.getClass().getEnclosingClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " +
threadLocal.getClass().getEnclosingClass().getName());
}
else if (threadLocal.getClass() != null &&
threadLocal.getClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " + threadLocal.getClass().getName());
}
else {
logger.info("threadLocalMap(" + i + "): cannot identify threadlocal class name");
}
}
}
The key "Transactional Resources" looks like you are talking to the database without a proper transaction. Make sure transaction management is configured properly and no invocation path to the DAO exists that doesn't run under a #Transactional annotation. This can easily happen when you configured transaction management on the Controller level but are invoking DAOs in a timer or are using #PostConstruct annotations. I wrote it up here http://georgovassilis.blogspot.nl/2014/01/tomcat-spring-and-memory-leaks-when.html
Edit: It looks like this is (also?) a bug with spring-data-jpa which has been fixed with v1.4.3. I looked it up in the spring-data-jpa sources of LockModeRepositoryPostProcessor which sets the "Transactional Resources" key. In 1.4.3 it also clears the key again.
Sometimes this has to do with configuration changes. When we upgraded from Tomncat 6.0.14 to 6.0.26, we had seen something similar. here is the solution
http://www.skill-guru.com/blog/2010/08/22/tomcat-6-0-26-shutdown-reports-a-web-application-created-a-threadlocal-threadlocal-has-been-forcibly-removed/
This problem appears when we are using any third party solution, without using the handlers for the cleanup activitiy.
For me this was happening for EhCache. We were using EhCache in our project for caching.
And often we used to see following error in the logs
SEVERE: The web application [/products] appears to have started a thread named [products_default_cache_configuration] but has failed to stop it. This is very likely to create a memory leak.
Aug 07, 2017 11:08:36 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/products] appears to have started a thread named [Statistics Thread-products_default_cache_configuration-1] but has failed to stop it. This is very likely to create a memory leak.
And we often noticed tomcat failing for OutOfMemory error during development where we used to do backend changes and deploy the application multiple times for reflecting our changes.
This is the fix we did
<listener>
<listener-class>
net.sf.ehcache.constructs.web.ShutdownListener
</listener-class>
</listener>
So point I am trying to make is check the documentation of the third party libraries which you are using. They should be providing some mechanisms to clean up the threads during shutdown. Which you need to use in your application.
No need to re-invent the wheel unless its not provided by them. The worst case is to provide your own implementation.
Reference for EHCache Shutdown
http://www.ehcache.org/documentation/2.8/operations/shutdown.html

How to fetch Entities, update in GWT, and save using JPA 2 in AppEngine?

After I update some Entities in GWT, I would like to save them. However, when I try to persist them, it does not save when I look in the AppEngine admin interface. The Boolean has not changed.
Code
EntityManager em = EMF.get().createEntityManager();
for (OnixUser s: admin) {
log.info(s.email + ", " + s.isAdmin);
em.merge(s);
}
em.close();
Update with transaction
EntityManager em = EMF.get().createEntityManager();
em.getTransaction().begin();
for (OnixUser s: admin) {
log.info(s.email + ", " + s.isAdmin);
OnixUser merged = em.merge(s);
em.persist(merged);
// em.persist(s);
}
em.getTransaction().commit();
em.close();
Still did not save. No exceptions thrown.
Log
Oct 16, 2013 3:19:10 PM com.example.sdm.server.SDMServiceImpl setAdmin
INFO: chloe#example.com, true
App Engine admin interface for OnixUser entity
Log at FINEST level
FINE: Created ManagedConnection using DatastoreService = com.google.appengine.api.datastore.DatastoreServiceImpl#2fd9270d
Oct 16, 2013 4:03:14 PM org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection
FINE: Connection added to the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection#31c1f89d for key=org.datanucleus.ObjectManagerImpl#6977c57b in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl#2b1f5f6b]
Oct 16, 2013 4:03:14 PM com.example.sdm.server.SDMServiceImpl setAdmin
INFO: chloe#example.com, true
Oct 16, 2013 4:03:14 PM org.datanucleus.state.LifeCycleState changeState
FINE: Object "com.example.sdm.shared.OnixUser#48ef6e99" (id="com.example.sdm.shared.OnixUser:6456332278300672") has a lifecycle change : "P_CLEAN"->"P_NONTRANS"
Oct 16, 2013 4:03:14 PM org.datanucleus.store.connection.ConnectionManagerImpl$1 managedConnectionPostClose
FINE: Connection removed from the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection#31c1f89d for key=org.datanucleus.ObjectManagerImpl#6977c57b in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl#2b1f5f6b]
Oct 16, 2013 4:03:14 PM org.datanucleus.state.LifeCycleState changeState
FINE: Object "com.example.sdm.shared.OnixUser#48ef6e99" (id="com.example.sdm.shared.OnixUser:6456332278300672") has a lifecycle change : "P_NONTRANS"->"DETACHED_CLEAN"
Oct 16, 2013 4:03:14 PM com.google.apphosting.utils.jetty.AppEngineAuthentication$AppEngineUserRealm disassociate
FINE: Ignoring disassociate call for: chloe#example.com
If inspite of using transactions your data is not persisted then best way would be to try the logging to see what's happening underneath. As you using DataNucleus as your persistence provider, you can refer to this link to configure
the SQL logging. The information relevant to you is given near the end of page.

Mahout Recommender Not Working Properly

I am working on Mahout and found an issue when I tried to change my csv, previously it was giving me proper recommendations.
Example code:
model = new FileDataModel(new File("E:\\WriteTest.csv"));
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
UserNeighborhood neighborhood = new NearestNUserNeighborhood(2,similarity,model);
Recommender recomender = new GenericUserBasedRecommender(model,neighborhood, similarity);
List<RecommendedItem> recommendations = recomender.recommend(1,1);
for(RecommendedItem recommendation: recommendations){
System.out.println(recommendation);
}
I have just updated the values of my csv and it has stopped giving me suggestion.
CSV that is not giving me any result:
1,13,9.9
1,26,9.0
1,40,4.0
2,83,9.9
2,167,9.0
2,250,4.0
3,91,9.9
3,167,9.0
3,274,4.0
4,91,9.9
4,167,2.0
CSV which is giving me result:
1,101,5.0
1,102,3.0
1,103,3.0
2,101,5.0
2,102,2.5
2,103,3.0
2,104,2.1
3,101,5.0
3,102,2.5
3,105,4.0
3,107,5.0
4,102,2.0
4,104,4.0
4,105,2.5
4,106,3.0
4,107,2.6
5,101,5.0
5,102,3.4
5,104,2.5
5,105,2.5
5,106,1.0
Output on console respectively:
Result from 1st Dataset Aug 27, 2011 2:45:06 AM
org.slf4j.impl.JCLLoggerAdapter info INFO: Creating FileDataModel for
file WriteTest.csv Aug 27, 2011 2:45:06 AM
org.slf4j.impl.JCLLoggerAdapter info INFO: Reading file info... Aug
27, 2011 2:45:06 AM org.slf4j.impl.JCLLoggerAdapter info INFO:
Readlines: 11 Aug 27, 2011 2:45:06 AM org.slf4j.impl.JCLLoggerAdapter
info INFO: Processed 4 users
I was expecting Item no 167 but din't find any recommendation
Output of 2nd dataset:
Aug 27, 2011 2:52:42 AM org.slf4j.impl.JCLLoggerAdapter info
INFO: Creating FileDataModel for file WriteTest.csv
Aug 27, 2011 2:52:42 AM org.slf4j.impl.JCLLoggerAdapter info
INFO: Reading file info...
Aug 27, 2011 2:52:42 AM org.slf4j.impl.JCLLoggerAdapter info
INFO: Read lines: 21
Aug 27, 2011 2:52:42 AM org.slf4j.impl.JCLLoggerAdapter info
INFO: Processed 5 users
RecommendedItem[item:105, value:3.25]
The recommender is working correctly. The problem is that your data is too sparse. It cannot find a similarity that would link two users such that 167 is recommendable. Try a more realistic data set and I think the behavior will look less surprising.

Categories