With the 3.2 release, one way to get around this problem is to define the foreign key fields. So for the 'many' object', you define the foreing key field and when you call ejbcreate , you set it. This will avoid your NOT NULL problem.
Thanks for the reply, I added <fk-constraint>true</fk-constraint> to <ejb-relationship-role> as you said but still got problems ... is this what you mean by defining foreign key fields? am I missing something else ? Thanks again!
No I mean add the field as a normal field using setter and getters, then when you call ejbCreate() set the value of the field.
So, say you have a 'one' object, and a 'many' object has a field that holds the value to the foreign key (pointing to the one object/table), when you call ejbCreate() in the 'many' object you set the value of the field for the foreign key. This avoids NOT NULL exceptions.
This has been an issue I have been grappling with for a while. You might want to check other threads in which I asked the same question.
By the way, Hibernate is a pretty awesome o/r mapper. You might want to look at it. By using Hibernate in a Session bean, JBoss handles threading, transactions, database configuration and pooling, and Hibernate seamlessly maps the objects to the tables.
I encountered this same problem. I am using middlegen to create the entity beans from an evolving schema, so I was motivated to figure out a workaround that didn't involve custom rewrites. It turns out that the middlegen Data Object constructor is just the ticket.
Here is my middlegen target
(I also have a file in my merge directory called cmp20-ALL-class-comments.txt that contains the line
* @ejb-transaction type="Required"
since middlegen seems to have forgotten about the need to specify transaction types.)
The generated code adheres to the classic EJB pattern for the custom constructors, but uses the pattern described by tommyg for the data object constructor. So by calling the data object version in my session beans, I get to keep the NOT NULL constraint on all my foreign key fields without having to rewrite any of the middlegen-generated source files.
hope this helps
urk, I posted too soon. Turns out that the xDoclet generated xCMP.java file edits out relationship fields in setData(). The workaround is to patch xdoclet-ejb-module-1.2b2.jar by changing line 52 of entity-body.xdt from
Setting the foreign key field in ejbCreate() instead of ejbPostCreate() works fine in JBoss but not in Weblogic. I need a solution which will work across app servers. I define the foreign key column as both a CMF and CMR field. When setting the foreign key field in ejbCreate(), I use the CMF version. When I want to use the relationship, I use the CMR version. Weblogic does not allow me to use the CMR version in ejbCreate(). Anybody got this working across app servers, without losing the NOT NULL attribute on the foreign key column?
This seems to work. If the foreign key is also part of the primary key, then weblogic and jboss both allow the CMP-field to be set in ejbCreate(), otherwise the foreign key field must be set in ejbPostCreate() and must allow nulls. So it appears that if you want a foreign key to be NOT NULL, it must be part of the primary key.
Using 3.2, I'm unable to set the foreign key in ejbCreate() when using foreign key CMP. The server throws the following error:
javax.ejb.EJBException: null; CausedByException is:
A CMR field cannot be set in ejbCreate; this should be done in the ejbPostCreate method instead [EJB 2.0 Spec. 10.5.2].
It knows you're breaking the spec and doesn't let you do it!
The only other solution I've seen to this problem is to delay the not null constraint checking until the transaction is committed. Well not every database can do this. It seems to me that JBoss should delay the initial database insert until after ejbPostCreate has been called. Is this planned? 4.0 maybe?
There seems a few threads related to this topic (but the forum seach seems very unreliable), this is my understanding of the CMR mapping to CMP solution to this problem.
In ejb-jar.xml insert a CMP field in the bean with the foreign key.
In jbosscmp-jdbc.xml map the new CMP field to the foreign key database column.
In the EJB code insert Abstract get/set methods for the new CMP field. In the ejbCreate populate the CMP field with the related key.
(This ensures that when the insert occurs after ejbCreate the foreign key isn't null).
Populate the CMR as usual in ejbPostCreate.
It's a bit of a bodge, and I agree it would be better to have the option to delay the insert until after ejbPostCreate.