by
Version: 1.2beta
$Id: $
Well, as Scott Ambler writes in his article "Enterprise-Ready Object IDs" , however you want to have it, most of us who are developing in the EJB world use relational databases to store objects. And where as relational databases need keys, objects don't.
Here is a proposal for an Enterprise-ready, Simple, Performant, Scalable, Plateform-independant EJB Primary Key Generator.
This is explained in this article
The latest stable version of EJBUtils binary and source editions can be downloaded from SourceForge at http://sourceforge.net/project/showfiles.php?group_id=13840.
The binary edition contains a trimmed down version of the orginal build file that will help you creating the table, creating the client jar file and deploy EJBUtils.
It also contains the source code, but for reference only. If you wish to build EJBUtils, download the source edition.
See the section Building EJBUtils on how to build EJBUtils from the source code.
To build and use EJBUtils, you must have successfully installed Ant version 1.3 or above and set the
ANT_HOME
environment variable as explained in the Ant doc. You can download Ant on the Apache website at http://jakarta.apache.org/ant/index.html.
Deployement of EJBUtils is also supported for JBoss 2.1 and above. If you whish to be able to deploy, you will have to download JBoss at www.jboss.org
The JDK used for developement was JDK 1.2 or later.
Make a copy of the default_build.properties
and rename it build.properties
. Follow the instructions commented in the file including changing uniqueid
properite. (for more information on the role of the uniqueid, read the article and search for "unique identifier")
You need to type the following command
ant create-table
Note: if some properties that need to be set are not, a message will appear. Just follow the instructions.
Also if you need to remove the table you can use the following command:
ant remove-table
EJBUtils uses by default the Hypersonic datasource blundled with JBoss. This is only for the purpose of the
example: Hypersonic does not support "For Update"
SQL statement (or for the matter transaction
isolation levels), and therefore is unfit for the UID generator.
You need a database that supports "For Update"
and you need to create a datasource accessing it in JBoss (please see JBoss doc).
Set your newly created datasource in the src/etc/DeployEJB/META-INF/jboss.xml
file for use by EJBUtils. (replace
DefaultDS
in the example below).
<jboss> <secure>false</secure> <container-configurations></container-configurations> <resource-managers> <resource-manager res-class="org.jboss.ejb.deployment.JDBCResource"> <res-name>UIDHighKeyGeneratorDS</res-name> <res-jndi-name>java:/DefaultDS</res-jndi-name></resource-manager></resource-managers> ... </jboss>
Note: If you wish, you could still use Hypersonic for trial purposes but THE UID GENERATOR WOULD BE UNFIT FOR PRODUCTION as it will not guaranty that the HIGH value obtained through the database call is unique. This involves some code change and you will need the source distribution of EJBUtils. For more information see this section of the HowTo guide.
You need to type the following command
ant deploy
Note: if some properties that need to be set are not, a message will appear. Just follow the instructions.
Follow the Step 1 and Step 2 of the Deploying on JBoss section. Then you will have to package
and deploy EJBUtils using the server's own deployment tool. Note that the original ejb-jar is lib/ejbutils-deploy.jar
Note: EJBUtils has to be deployed before you can run any tests against it. For more information see the section Deploying EJBUtils
EJBUtils comes with 2 tests:
ant -buildfile test.xml run-tests
Note: this test creates an ejb-jar called ejbutils-deploy-test.jar
. If you use JBoss, it will be automatically deployed to it. If you deploy to another ejb server, you will have to deploy this manually.
ant -buildfile test.xml run-concurrency-tests
Tricks: To make sure that the concurrency test assurely checks concurrency properly, do the two following twicks:
For JBoss, make sure that your datasource declared in the jboss.jcml file has the following parameter:
<mbean code="org.jboss.jdbc.XADataSourceLoader" name="[whatever you datasource settings are]"> [...] <attribute name="MinSize">2</attribute> [...] </mbean>
"SELECT ... FOR UPDATE"
clause and the commit, which takes place when the end of the method calling it (transaction for this method is set to RequiresNew
). To make sure that concurrency is tested properly, a concurrent "SELECT ... FOR UPDATE"
has to be executed within this elapsed time. To make sure this happens uncomment the following code, which increases the elapsed time by 2 seconds (don't forget to comment the code back when you use EJBUtils in production environment) and redeploy EJBUtils:[UIDHighKeyGeneratorBean.java] public class UIDHighKeyGeneratorBean implements SessionBean { [...] public Key getNextHighKey(Key theHighKey, String theName) throws RemoteException, FinderException { [...] // Uncomment the two following lines if you would like to test concurrency long timeStamp = System.currentTimeMillis(); while (System.currentTimeMillis() " timeStamp + 2000) { } [...] } [...] }
See the section Deploying EJBUtils on how to deploy EJBUtils.
To build EJBUtils, you should install the EJBUtils source distribution. While the binary distribution includes the EJBUtils source code, it is intended for reference purposes only. Only a trimmed down version of the build script used to build EJBUtils is not included in the binary distribution.
Once you have installed the source distribution, go to the
ejbutils-x.x
directory (replace x.x
with the version of EJBUtils).
To build EJBUtils, use:
ant distribution
to create a binary distribution of EJBUtils. This distribution can be
found in the distribution
directory.
ant build
ant jars
See the section Deploying EJBUtils on how to deploy EJBUtils.
See the section Using EJBUtils on how to use EJBUtils.
After you have deployed EJBUtils, you can write code to use it and include the libraries to you deployed code.
Your primary key has to be a String
. If you use a database as Datastore, use a CHAR(55)
to store the primary key field. It should be enough for the vast majority of cases. In the example below, we use String as a simple primary key for our entity bean.
[...] import javax.ejb.EJBException; import org.ejbutils.uid.UIDDispenser; import org.ejbutils.uid.UIDDispenserException; public class MyEntityBean implements EntityBean { [...] /** @primaryKey */ public String objectId; public String ejbCreate() throws CreateException, RemoteException { try { this.objectId = UIDDispenser.getDispenser().getNextId(); } catch (UIDDispenserException e) { throw new EJBException(e.toString()); } return this.objectId; } [...] }
You could also encapsulate this code in an abstract class the following way:
[AbstractEntityBean.java] import javax.ejb.EJBException; import org.ejbutils.uid.UIDDispenser; import org.ejbutils.uid.UIDDispenserException; public abstract class AbstractEntityBean { public String provideObjectID() throws EJBException{ String anObjectID; try { anObjectID = UIDDispenser.getDispenser().getNextId(); } catch (UIDDispenserException e) { throw new EJBException(e); } return anObjectID; } } [MyEntityBean.java] [...] public class MyEntityBean extends AbstractEntityBean implements EntityBean { [...] /** @primaryKey */ public String objectId; public String ejbCreate() throws CreateException, RemoteException { this.objectId = provideObjectID(); return this.objectId; } [...] }
One can deploy EJB modules on an EJB server in one of two ways: by deploying directly the EJB module (ejb-jar file) or by deploying through an Application Archive (ear file).
The EJB spec give two options to the EJB server vendors:
Exctract of the EJB 1.1 Spec, chapter 17.4:
[The EJB specification does not specify whether the ejb-jar file should include by copy or by reference the classes that are in the ejb-client JAR. If the by-copy approach is used, the producer simply includes all the class files in the ejb-client JAR file also in the ejb-jar file. If the by-reference approach is used, the ejb-jar file producer does not duplicate the content of the ejb-client JAR file in the ejb-jar file, but instead uses a Manifest Class-Path entry in the ejb-jar file to specify that the ejb-jar file depends on the ejb-client JAR at runtime.]
So you have to act depending on what your server supports:
by-copy
, copy the content of the lib/ejbutils-client.jar
file.
Do not forget to include the UIDDispenser.properties
file containing your unique identifier
(the sub-section Creating the ejbutils-client.jar
file will give you
more information on the unique identifier).by-reference
, add "Class-Path: ejbutils-client.jar
" in the
manifest file of you ejb-jar file (do not forget to add a carriage return after this line, otherwise there is a
bug in the jvm that will prevent the line from being read), and place the ejbutils-client.jar
file in the appropriate place of your EJB server.
ejbutils-client.jar
file. See the sub-section
Creating the ejbutils-client.jar
file.IMHO this is the cleanest way of deploying your EJBs. The only thing you need to do in this case is to include the ejbutils-client.jar
in your ear file and add the following Class-Ref in your ejb-jar file's manifest file: (do not forget to add a carriage return after this line, otherwise there is a bug in the jvm that will prevent the line from being read.)
Note: you have to create your own ejbutils-client.jar
file. See the sub-section Creating the ejbutils-client.jar
file.
Class-Path: ejbutils-client.jar
ejbutils-client.jar
fileA truly universal OUID needs a unique identifier identifying uniquely your company. The singleton gets this unique identifier through a resource file called UIDDispenser.properties
To create the ejbutils-client.jar
file with the UIDDispenser.properties
containing your unique identified, simple run
ant jars
and your ejbutils-client.jar
file will be either in the build/lib
directory (source distribution) or the lib
directory (binary distribution).
For more information on the role of the unique identifier, read the article and search for "unique identifier".
If you want to contribute to EJBUtils or stay current with the latest development, join the EJBUtils Development Mail List (http://lists.sourceforge.net/lists/listinfo/ejbutils-devs).
To provide feedback on this software, please subscribe to the EJBUtils User Mail List (http://lists.sourceforge.net/lists/listinfo/ejbutils-user).
Archives of both lists can be found on the subscription web pages mentioned above.
If you want to submit a bug, place a support request or a feature request, go to http://sourceforge.net/tracker/?group_id=13840.
Copyright © 2000-2001 E.H.S. Technologies (Europe) Ltd. All rights Reserved.