You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Yuri <yd...@gmail.com> on 2008/11/14 07:04:04 UTC

Customizing OpenJPA

I started running through a few debugging sessions to understand the design
and come up for a course of action in terms of extending OpenJPA. A few
questions came up:

- How can a ProductDerivation be used to extend OpenJPA (I am assuming that
is its purpose)?
- What is the difference between ProductDerivation.TYPE_PRODUCT and
ProductDerivation.TYPE_FEATURE
- What is the difference between ClassMetadata and MappingInfo? It seems
that the latter is a temporary holder of schema objects until the final
ClassMetadata is assembled. Is that correct?
- Noticed that the enhancement on class loading is no using the classes I
created to extend OpenJPA (i.e. Configuration and what follows from that). 
- Also noticed that MetadataRepository is created at least two times once
when enhancing and once for real.

I am planning initially to add a new @Temporal annotation and to make sure
that this annotation translates into additional columns in the table, into a
modified primary key and custom handling of the SQL statements. What would
be the main touch points in the code to make that happen?

thanks,

-- yuri
-- 
View this message in context: http://n2.nabble.com/Customizing-OpenJPA-tp1497344p1497344.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Re: Customizing OpenJPA

Posted by Yuri <yd...@gmail.com>.
FWIW, here is a simple class diagram to help me navigate the design...

http://n2.nabble.com/file/n1623649/openjpa.gif 
-- 
View this message in context: http://n2.nabble.com/Customizing-OpenJPA-tp1497344p1623649.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Re: Customizing OpenJPA

Posted by Yuri <yd...@gmail.com>.

Patrick Linskey-2 wrote:
> 
>> - Noticed that the enhancement on class loading is no using the  
>> classes I
>> created to extend OpenJPA (i.e. Configuration and what follows from  
>> that).
>> - Also noticed that MetadataRepository is created at least two times  
>> once
>> when enhancing and once for real.
> 
> These are probably related -- the enhancer by default uses a plain  
> OpenJPAConfigurationImpl instance instead of a JDBCConfigurationImpl  
> or whatever subclass is available in the environment. In general, the  
> enhancement contract is simply a way to plug into objects for the  
> purposes of interacting with their persistent state, and so the back- 
> end-specific details must not be relevant. IOW, it is a design goal to  
> be able to support different back-ends for the same enhanced classes.
> 
> Is there something that you find that you need to do during  
> enhancement for your task?
> 

Not at this point. It was a question that came up while trying to create a
mental picture of the design and the main components. The more I learn about
the design the more it makes sense the fact that it will be very unlikely I
will have to mess with the enhancer.


Patrick Linskey-2 wrote:
> 
> What is the goal of your work? Also, is @Temporal targeted at the  
> class level or the field level, or both?
> 

The goal is to provide versioning of persistent models by simply adding
@Temporal to the classes one wishes to version (with a few additional
parameters for customizations e.g. what is the name of the valid time
column, granularity - millis, days, hours). At this point I am not
interested in providing a full bi-temporal solution just a valid time
temporality that is, to the extent possible, orthogonal to the persistent
model.

This extension starts with the @Temporal annotation, transforms the
persistent class' id into id + validEnd, rewrite the implementation of a
logical inserts, updates, deletes, and selects, internally forces the
immutability of the persistent model (the Entity state will be divided into
two objects: a temporal aware proxy and a state object that is a mirror of
what is in the db - the proxy will be aware of what is the current time for
the query). Then once the main infra is implemented I am planning to extend
the query language to allow for queries across valid time.


Patrick Linskey-2 wrote:
> 
> Assuming that you're looking into adding object versioning support to  
> OpenJPA, I believe that there are two general approaches that you  
> should consider:
> 
> 1. change the ClassMappings (or things they use) to know about  
> temporal information, and to translate the various Broker-level / EM  
> APIs to their temporal equivalents (EntityManager.remove() => an  
> UPDATE statement; modifications => UPDATE / INSERT pairs, add  
> timestamp range qualifications to queries and relationships, etc.)
> 
> 2. add a new StoreManager implementation that does the above  
> translations at the generic object level and delegates to an  
> underlying StoreManager.
> 
> 
> I'm not sure which approach I like the most. #2 seems more natural, as  
> it operates at the object persistence level, rather than in the JDBC  
> nitty-gritty. But #1 might be more straightforward to implement, since  
> there isn't currently a clean and simple way to add synthetic  
> persistent fields or field-like things to a class, whereas it is  
> straightforward to do so at the JDBC layer.
> 

I think my confused thoughts are more in line with your #1 above, although
it seems to me that the touch points will be much larger than just the
ClassMapping. I am sure that half of it is my ignorance of the
implementation. 

Here is my understanding so far of what needs to be done:
- The first thing I need to do is create the class level @Temporal
annotation and make sure the AnnotationPersistenceMappingParser is able to
handle it. It seems that I will need to subclass
AnnotationPersistenceMappingParser and override
handleUnknownClassMappingAnnotation() (Later support for xml can be added).

- The annotation parser will then add two FieldMappings, one for validStart
and one for validEnd. The validEnd FieldMapping will be set as primary key.
Here I am assuming that the back end will automatically generate the right
table schema with the two added columns and the composite pk.
    * Is this the right place to be adding these synthetic FieldMappings? I
think I saw a subclass of ClassStrategy.map() performing metadata and/or
schema modifications somewhere in the code.

- Then I will need to install custom ClassStrategy that rewrites
inserts/updates/selects/deletes. Not sure if I need also to override
FieldStrategy or even if I need to create a custom TemporalClassMapping
and/or TemporalFieldMapping. It seems that there is much more here than meet
the eyes...

- Then I need to extend StateManager to include two new attributes
validStart and validEnd since they dont actually exist in the PC. I also
need to figure how to make sure that the impl doesnt try to get these two
values from the PC object (not sure exactly where yet)

- I am also expecting some sort of StateManager proxy that holds a given
point in time (timestamp) in addition to a reference to the original
StateManager. This is needed I think since the row that comes back from a
given PC is valid for a data range and the fact that each end of a relation
could have different ranges:  basically different queries could thread
differently through the relations.


At this point I am also not sure how/where #2 fits in the above steps.

Hope my loose thoughts above are not too confusing.

thanks for you help,

-- yuri
-- 
View this message in context: http://n2.nabble.com/Customizing-OpenJPA-tp1497344p1623623.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Re: Customizing OpenJPA

Posted by Patrick Linskey <pl...@gmail.com>.
> - What is the difference between ClassMetadata and MappingInfo? It  
> seems
> that the latter is a temporary holder of schema objects until the  
> final
> ClassMetadata is assembled. Is that correct?

Yes. OpenJPA parses from various different formats into MappingInfo  
data structures, and then the ClassMetaDatas are created from the  
MappingInfo.

> - Noticed that the enhancement on class loading is no using the  
> classes I
> created to extend OpenJPA (i.e. Configuration and what follows from  
> that).
> - Also noticed that MetadataRepository is created at least two times  
> once
> when enhancing and once for real.

These are probably related -- the enhancer by default uses a plain  
OpenJPAConfigurationImpl instance instead of a JDBCConfigurationImpl  
or whatever subclass is available in the environment. In general, the  
enhancement contract is simply a way to plug into objects for the  
purposes of interacting with their persistent state, and so the back- 
end-specific details must not be relevant. IOW, it is a design goal to  
be able to support different back-ends for the same enhanced classes.

Is there something that you find that you need to do during  
enhancement for your task?

> I am planning initially to add a new @Temporal annotation and to  
> make sure
> that this annotation translates into additional columns in the  
> table, into a
> modified primary key and custom handling of the SQL statements. What  
> would
> be the main touch points in the code to make that happen?

What is the goal of your work? Also, is @Temporal targeted at the  
class level or the field level, or both?

Assuming that you're looking into adding object versioning support to  
OpenJPA, I believe that there are two general approaches that you  
should consider:

1. change the ClassMappings (or things they use) to know about  
temporal information, and to translate the various Broker-level / EM  
APIs to their temporal equivalents (EntityManager.remove() => an  
UPDATE statement; modifications => UPDATE / INSERT pairs, add  
timestamp range qualifications to queries and relationships, etc.)

2. add a new StoreManager implementation that does the above  
translations at the generic object level and delegates to an  
underlying StoreManager.


I'm not sure which approach I like the most. #2 seems more natural, as  
it operates at the object persistence level, rather than in the JDBC  
nitty-gritty. But #1 might be more straightforward to implement, since  
there isn't currently a clean and simple way to add synthetic  
persistent fields or field-like things to a class, whereas it is  
straightforward to do so at the JDBC layer.

-Patrick

On Nov 13, 2008, at 10:04 PM, Yuri wrote:

>
> I started running through a few debugging sessions to understand the  
> design
> and come up for a course of action in terms of extending OpenJPA. A  
> few
> questions came up:
>
> - How can a ProductDerivation be used to extend OpenJPA (I am  
> assuming that
> is its purpose)?
> - What is the difference between ProductDerivation.TYPE_PRODUCT and
> ProductDerivation.TYPE_FEATURE
> - What is the difference between ClassMetadata and MappingInfo? It  
> seems
> that the latter is a temporary holder of schema objects until the  
> final
> ClassMetadata is assembled. Is that correct?
> - Noticed that the enhancement on class loading is no using the  
> classes I
> created to extend OpenJPA (i.e. Configuration and what follows from  
> that).
> - Also noticed that MetadataRepository is created at least two times  
> once
> when enhancing and once for real.
>
> I am planning initially to add a new @Temporal annotation and to  
> make sure
> that this annotation translates into additional columns in the  
> table, into a
> modified primary key and custom handling of the SQL statements. What  
> would
> be the main touch points in the code to make that happen?
>
> thanks,
>
> -- yuri
> -- 
> View this message in context: http://n2.nabble.com/Customizing-OpenJPA-tp1497344p1497344.html
> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>

-- 
Patrick Linskey
202 669 5907