This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Object Relational Mapping and the fly likes Spring/JPA/TopLink 11g extensions Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Spring/JPA/TopLink 11g extensions" Watch "Spring/JPA/TopLink 11g extensions" New topic
Author

Spring/JPA/TopLink 11g extensions

Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi,

Im currently trying to use Spring/JPA with some TopLink 11g extensions for Conversion but are unable to get this working.
I have tried a lot of different converters but it seems like all my TopLink annotations are ignored.

I would really appriciate all help I can get on this.

Iv included a small "dummy" below.

When using the converter on the class below I was hoping that the generated schema would be like:

CREATE TABLE TYPECONVTEST (ID NUMERIC(19) NOT NULL, AGE VARCHAR2(255), PRIMARY KEY (ID))

But the generated schema is:

CREATE TABLE TYPECONVTEST (ID NUMERIC(19) NOT NULL, AGE INTEGER, PRIMARY KEY (ID))


Dummy example:



My Spring configuration is like this:

Mike Keith
author
Ranch Hand

Joined: Jul 14, 2005
Posts: 304
Hi Rune,

Why you are using a type converter if you are generating the schema. Why not just use an int on both sides? Converters are normally used for mapping an object model to a pre-existing legacy database, not when you have the choice to generate a schema.

If you are in a situation (either because you are just performing testing, or for whatever other reason the database you are generating needs to map an int in the object model to a string in the data model then you should be able to use the @Column annotation to explicitly dictate the column to get generated. For example:

@Convert("intToString")
@Column(name="AGE", columnDefinition="VARCHAR2(255)")
int age;


-Mike
Pro JPA 2: Mastering the Java Persistence API
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi Mike,

Thank you for your answer. I realize that the example Iv included was a bit to simple. It was just to illustrate that I did not manage to get any of the Oracle TopLink extensions annotations to work properly.

What Im really trying to do is to write a converter that converts the Eric Evans Time&money library class com.domainlanguage.time.CalendarDate. The CalendarDate class consist of three properties, i.e. year, month and day, which I want to persist as a date column in the database.

We could use embeddable, but this will not be possible due to the JPA limitation with embeddables (embeddable within embeddable).

Im really was hoping that the new feature in TopLink 11g would help me.

BTW. Iv managed to do this with TopLink essentials using a session custimizer, but I really would like to use the annotation style.

public class ConverterCustomizer implements SessionCustomizer {



Best regards,
Rune
Mike Keith
author
Ranch Hand

Joined: Jul 14, 2005
Posts: 304
Oh, so your real problem is simply that your annotations don't appear to be getting recognized? I can only think of a few things that could be causing that. Either your class is not being discovered (i.e. it is not packaged in a place where discovery is occurring) or it is not annotated as an entity. Other than that it could only be a configuration error (TopLink not being invoked for that entity, etc).

You can turn logging on to debug mode to see the entities it is finding. Do this by setting your logging property to "FINEST". I have noticed that the Spring "showSQL" property seems to hammer whatever the provider logging property is set to, so you need to remove the Spring property in order to set the logging to any other mode than FINE.
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Mike,

Thank you for taking interest in my issue.

I have set the logging level to FINEST and can see that my entity class is discovered and that a table is created.

--CREATE TABLE CUSTOMER (ID NUMERIC(19) NOT NULL, AGE NUMERIC(38), CALENDARDATE BINARY, PRIMARY KEY (ID))

The table is however not as expected as the converter annotations are not discovered. Im running the test as a JUnit test and have event tried to set a breakpoint in the converter class. It does not break.

I did however make a small test using a standalone Java application without Spring. Then the converter annotations was discovered and the create table statement was as expected.

--CREATE TABLE CUSTOMER (ID NUMERIC(19) NOT NULL, AGE VARCHAR(255), CALENDARDATE DATE, PRIMARY KEY (ID))

My conclusion is that it must have something to do with my Spring configuration. Could it have something do with not using the oracle.toplink.ejb.cmp3.EntityManagerFactoryProvider directly as I do in the standalone application?

I have included the not working example and my Spring configuration below.

Many thanks
Rune

Entity class



applicationContext.xml



persistence.xml



orm.xml

I have removed this file since Im only using annotations.
Mike Keith
author
Ranch Hand

Joined: Jul 14, 2005
Posts: 304
Hi Rune,

DDL generation occurs through a slightly different path in a container than when using the factory API. One possibility is that the TopLink annotations are not recognized in the Container scenario until after the generation. You can test this out in one of two ways.

You can use the Column annotation to cause the correct column type to be generated and then run a few tests that will test whether the types get converted at runtime (if they do then the annotations were indeed detected, they just weren't used at generation-time).

Another thing to try is to change the Spring factory bean to be a LocalEntityManagerFactoryBean instead of a LocalContainerEntityManagerFactoryBean. This will cause Spring to use the regular factory API instead of the special container API and you can compare the results.
James Sutherland
Ranch Hand

Joined: Oct 01, 2007
Posts: 553
Make sure you are using TopLink 11g, not TopLink Essentials in your Spring server. You should see the TopLink version printed in your TopLink log, does it say 11g or Essentials?


TopLink : EclipseLink : Book:Java Persistence : Blog:Java Persistence Performance
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi,

I tried to use the LocalEntityManagerFactoryBean and then the annotations was detected. The log below shows that the default serialization is ignored due to the @Convert annotation.


TopLink Finest]: 2007.11.14 03:34:01.077--ServerSession(32486590)--Thread(Thread[main,5,main])--property=toplink.orm.throw.exceptions; default value=true
[TopLink Finer]: 2007.11.14 03:34:01.077--ServerSession(32486590)--Thread(Thread[main,5,main])--Searching for default mapping file in file:/C:/devtools/NG/eclipse/workspace/JpaTestProject%20-%20TopLink%2011g/target/classes/
[TopLink Config]: 2007.11.14 03:34:01.280--ServerSession(32486590)--Thread(Thread[main,5,main])--The alias name for the entity class [class com.statoil.sas.invpilot.customer.domain.Customer] is being defaulted to: Customer.
[TopLink Config]: 2007.11.14 03:34:01.280--ServerSession(32486590)--Thread(Thread[main,5,main])--The table name for entity [class com.statoil.sas.invpilot.customer.domain.Customer] is being defaulted to: CUSTOMER.
[TopLink Config]: 2007.11.14 03:34:01.312--ServerSession(32486590)--Thread(Thread[main,5,main])--The column name for element [private long com.statoil.sas.invpilot.customer.domain.Customer.id] is being defaulted to: ID.
[TopLink Config]: 2007.11.14 03:34:01.343--ServerSession(32486590)--Thread(Thread[main,5,main])--The column name for element [private java.lang.Number com.statoil.sas.invpilot.customer.domain.Customer.age] is being defaulted to: AGE.
[TopLink Warning]: 2007.11.14 03:34:01.343--ServerSession(32486590)--Thread(Thread[main,5,main])--Ignoring default serialization on element [private java.lang.Number com.statoil.sas.invpilot.customer.domain.Customer.age] within entity class [class com.statoil.sas.invpilot.customer.domain.Customer] since a @Convert is specified.



Then, when using the LocalContainerEntityManagerFactoryBean I get the following log. As you can see, there is no indication of any Converters:-(




As you can see Im using TopLink 11g. Have any of you tried using toplink 11g annotations successfully with Spring LocalContainerEntityManagerFactoryBean?

Still struggling and hoping:-)

Best regards,
Rune
James Sutherland
Ranch Hand

Joined: Oct 01, 2007
Posts: 553
Very odd, the only thing I can think of is that you are deploying different code somehow with the Container deployment. Try changing something else in the class and see if it is picked up.

If still no luck, try other annotations add see if they have the same issue.
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi James,

I have tried to use several different annotations and have also changed different parts of the entity. It all results in the same, TopLink annotations not beeing discovered when using the LocalContainerEntityManagerFactoryBean and not discovered when using the LocalEntityManagerFactoryBean.

Im not really deploying to a server as Im running it withing Eclipse. Could that be a problem?

Is it at all possible that this is a bug?

Have you tried this before? Do you have any working examples?

I could of course email you my test project, but I guess you are to busy to test it, or?:-)

Many thanks,
Rune
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi again,

Another question,

Is it possible to configure a converter using an alternative approach?
I know it is possible using a session customizer, but is it possible to configure this in the orm.xml?

Best regards,
Rune
Mike Keith
author
Ranch Hand

Joined: Jul 14, 2005
Posts: 304
Hi Rune,

I think there actually is a problem with using Container API in Spring with TopLink-specific annotations. I tried it out and the container classloader in Spring loads them in a different classloader than what is expected. I could give you a patch for the Spring classloader class, but if you are not running in a server then you may as well just use the LocalEntityManagerFactoryBean. You are not losing anything at all, and you would just need to specify the TopLink agent jar when you start the application and you would get all the weaving, etc.
Rune Kvamme
Greenhorn

Joined: Nov 11, 2007
Posts: 7
Hi Mike,

Thank you very much, I really appriciate your help. We will be running our applications within a container, its just for testing purposes I have been running outside the container.

If you could supply me with at a patch for the Spring class loader I would be very greatful. Is this a bug in Spring or TopLink? Do you think it will will be fixed?

Many thanks:-)

Best regards,
Rune
Mike Keith
author
Ranch Hand

Joined: Jul 14, 2005
Posts: 304
Rune,

I wouldn't really consider it a bug in either Spring or TopLink, since both are actually correctly fulfilling their roles as Container and Provider using the SPI. The problem seems to be a side-effect of a few things mixed together. We will have to get together with the Spring guys and work out the best way to fix it long-term. The simplest fix is to put some code in the Spring classloader, but that might not be the best long-term solution. I will send you the patch.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Spring/JPA/TopLink 11g extensions
 
Similar Threads
org.springframework.beans.factory.BeanCreationException
data not persisted using hibernate spring integration
Dependency injection problem
how does rollbackFor work ?
Service layer injection is not working after i exposed service layer as webservice