Hi,
I would like to add a small (well a big for me) feature to Entity EJB 1.1 in
CMP mode.
Dirk Zimmermann has already make some changes for that and I would like to
extend them.
I also would like your opinion on that.
We could call it "Nested Properties in CMP".
Current State
-------------
When we define cmp-field, they are saved into a corresponding field in the
database. If the original java type is primitive, it is transform to sql
type. If the original java type is not, it is serialized and saved as
object.
When you read the database not from EJB, you need to deserialize the object
to get its value. Not a problem with JDBC but when you want to access the
database in other ways, you got stuck.
Dirk Improvement
----------------
The goal of Dirk (AFAIK) was in the case of one bean B reference Primary Key
of bean A as a field. Dirk wanted to also stored the "inside" fields of the
A Primary Key as primitive type when they are. In fact they almost always
are. One Primary Key class is often one (or multiple) primitive type like
an "int" for example.
So he added the possibility to add in jaws.xml
<cmp-field>
<field-name>apk.id</field-name>
<column-name>apkid</column-name>
</cmp-field>
In this case both apk is serialized AND the id inside apk is saved as
integer in a new field.
Then very easy now to sql JOIN two tables.
Very nice indeed :)
Wanted Improvement
------------------
Extend that to any "non-primitive" cmp-field.
If I have an Address as a cmp-field, I may want to "explode" it in multple
primitive fields street, city, zip, country and save these fields instead of
serializing Address.
The workaround to do that today is to have all Address attributes as EJB
cmp-fields and implement a Address getAddress() method inside the bean,
declare it in the remote interface, ... very borring in fact, not OO, and I
am very lazzy too.
If you change Address, you have to review all EJB that use Address, beurk.
If you want a finder method on Zip code of Address, you can not serialize
Address or if you do, you have to findAll() then verify
getAddress().getZip(), beurk.
I don't think this is against the 1.1 spec as the 9.4.1 chapter is very
"vague".
I also don't think it go against 2.0 spec as this is really not in conflict
with Dependant Objects which are more complex that my case. (in D.O. the
address could be shared by two entity beans for example, or stored in
another table).
The biggest warrning to make I think is regarding chapter 9.2 of the spec
2.0 which says :
" When designing an entity bean with container managed persistence, the
Bean Provider must be mindful
of the distinction between the client view of the entity bean and the
entity bean�s view of its persistent
state. In particular, there need be no direct relationship between the two.
While the EJB component
model provides a separation between the client view of a bean (as presented
by its home and remote
interfaces) and the entity bean instance (which provides the implementation
of the client view), the EJB
architecture for container managed persistence adds to this a separation
between the entity bean
instance (as defined by the bean provider) and its persistent state."
I really think this improvement does not go against that because I am
focusing on very basic views : Address, Quantity, ...
The kind of fields that you do not want to transform each time in the EJB to
provide a client with its own view.
A Quantity is a Quantity ! for both server side componants and client side
components. For the Address example, it depends of what you want to do with
the Address, right. But if you know what you are doing . . .
How I plan to do it
-------------------
I would like to do that without changing the default behavior, so my ejb-jar
remains unchanged and define Address as the cmp-field. (This is what I want
to "publish" in my get/set in the remote interface). The changes would
appear in jaws.xml.
1. If I do not specify anything, Address is still serialized as before.
2. If I specify Address, Address is still serialized as before.
3. If I add Address.zip like this
<cmp-field>
<field-name>address.zip</field-name>
<column-name>addresszip</column-name>
</cmp-field>
I will have both Address Serialized and Address.zip saved in 2 columns.
Address remains the important data (If I change Address my sql, my EJB show
the change - If I change addresszip by SQL then my EJB do not see anything).
This would be helpful for "Catalog" pattern sort of things in Read Only SQL
only.
4. If I tell Jaws that Address is "exploded", then Address will be
reconstruct from its different fields.
Address would be exploded if I do not specify any <column-name> for it.
<cmp-field>
<field-name>address</field-name>
<column-name></column-name>
</cmp-field>
<cmp-field>
<field-name>address.street</field-name>
<column-name>addr-treet</column-name>
</cmp-field>
<cmp-field>
<field-name>address.zip</field-name>
<column-name>zip</column-name>
</cmp-field>
If I forgot (as in this example) to map some fields, they will be mapped by
default to
address_fieldname
I tell Jaws to explode a cmp-field by not specifying a column-name for it.
IMHO that's a simple trick that will permit to transform a lot of code
working now with a minimum amount of change. (I am an addict to ejbdoclet
and I ant to keep this change as transparent as possible).
5. This has to work recursively and automatically for nested properties.
If Address and a street property which is himself 3 String line1, line2,
line3,
Then I only have to specify
<cmp-field>
<field-name>address</field-name>
<column-name></column-name>
</cmp-field>
And I will get in my database
address_street_line1
address_street_line2
address_street_line3
address_zip
address_city
address_country
So per default I automatically explode the nested properties. Not
automatically for the first field to keep the standard behaviour.
6. Yes you have to create a jaws.xml to make it work! I do not use them and
try to make jaws work per default most of the time. Maybe a flag in
standardjaws.xml would be an idea.
<explode-nested-properties>
true
</explode-nested-properties>
This would make (5) work without having to write a jaws.xml.
But maybe it is going too far.
7. Finder Methods
They will work better with this!
You can now have a findByZip(String zip) method on the bean.
findByAddress() is no more possible but not needed as well.
For the Quantity object, if it has a double value and a String unit, you
could now have a findByUnit()
[Future] Arrays and Collections
-------------------------------
This could be extended for Arrays (and Collections).
Here I face the problem that Array is not a SQL standard (I have seen them
in Postgres but not in Hypersonic)
If an cmp-field is an Array and the database allows Arrays, it should be
possible to map these fields to SQL arrays and not Serialize them.
If Address define String[] street, today it is serialized, I would like to
create a VARCHAR[] field in compliant database instead.
This is for the future as it will require a lot more work to verify all
supported databases and I am not really sure I am going too far here. . .
Please give your opinion.
Vincent.
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development