The Source for Java Technology Collaboration
User: Password:



Brian Leonard's Blog

November 2006 Archives


Using Composite Keys with JPA

Posted by bleonard on November 29, 2006 at 09:14 AM | Permalink | Comments (14)

The Java Persistence API is beautiful. I create a class, annotate it with @Entity and @Id and I'm on my way. That is, however, assuming the Id is of a simple type (I'm a firm believer that primary keys should be of a simple type, unrelated to the data they index.). However, if you find yourself in a situation where you must use a composite key (hopefully this is only because you're connecting to some existing data set), JPA will still work for you, although it gets a bit more complex. First of all, you can declare a composite primary key using one of two annotations: @IdClass or @EmbeddedId. In this blog, I'm going to focus on the latter.

Using @EmbeddedId

A composite primary key must be represented by a primary key class. And when using the @EmbeddedId approach, it must be annotated as @Embeddable.

@Embeddable
public class ContactPK implements Serializable {

    @Column(name = "FIRSTNAME", nullable = false)
    private String firstname;

    @Column(name = "LASTNAME", nullable = false)
    private String lastname;

    ...

The primary key in the entity class is annoated with @EmbeddedId annotation:

@Entity
public class Contact implements Serializable {

    /**
     * EmbeddedId primary key field
     */
    @EmbeddedId
    protected ContactPK contactPK;

    ...

However, it doesn't stop there. The entity class must also implement the hashcode() and equals() methods. As I mentioned in my introduction, hopefully you're only using composite keys if you already have existing tables defined that way. In the spirit of that assumption, we're going to start with a table and just use NetBeans to create our entity class.

Setting Things Up

To continue we need NetBeans 5.5 and the Java EE Application Server 9.0. If you need both, just download and install the bundle.

Creating the Table

CompositeCustomer.sql will create a table with a composite primary key populated with some sample data.

  1. Save the CompositeCustomer.sql file somewhere on your disk.
  2. Open the file in NetBeans (Ctrl+O).
  3. On the SQL editor's toolbar, you'll see a Connection drop-down box. Select the jdbc:derby://localhost:1527/sample [app on APP] entry.



  4. Click the Run SQL icon on the right of the Connection drop-down box. This will open the Connect dialog. The password is app. Click OK to connect and run the SQL script.
  5. You can now view the table in the Runtime window:


Generating Entities With Composite Keys

The setup was the hard part. To create the entity class:

  1. Create a new Web Application project named CompositeKey.
  2. Add a new file (Ctrl+N) and select Persistence > Entity Classes from Database
    1. Select jdbc/sample as the Data Source and COMPOSITE_CUSTOMER as the table. Click Next.
    2. Set the Package to entity and click Create Persistence Unit.
      1. On the Create Persistence Unit dialog, just click Create.
    3. Click Finish

And you're done. The wizard created the primary key class, CompositeCustomerPK as well as the entity CompositeCustomer.

Testing the Entity

Here we'll delete our table and let JPA re-create it for us.

  1. Switch to the Runtime window, select the COMPOSITE_CUSTOMER table and press Delete.
  2. Switch to the Projects window and open up persistence.xml (under the Configuration Files folder). Change the Table Generation Strategy to Create
  3. Right-click the CompositeKey project and select Deploy Project. This will start the Sun Java System Application Server, if not already running, and deploy the project.
  4. Switch back to the Runtime window, right-click the Tables folder and select Refresh. JPA has re-created the table for us (sans the sample data, of course).


A Conversation with Seam

Posted by bleonard on November 15, 2006 at 10:51 AM | Permalink | Comments (1)

Another one of Seam's compelling features is its ability to manage "conversations". A Seam conversation provides fine grain control over the traditional HTTP session scope so that "concurrent conversations" can occur in HTTP session, which usually occur when users open another browser window or tab. The problem is best described with an example. I've added a confirmation page to the registration application used in my previous blog entries. So consider this application use case:

I launch the application and enter my registration information:

And the Registration page takes me to a confirmation page:

However, rather than completing the transaction (or conversation), I open a new browser tab and decide to register my brother as well:

And click Register to load his confirmation page:

But before completing this 2nd transaction (conversation), I return back to the registration tab with my registration details and now decide to complete the original transaction (conversation):

 

Hmmm, not was I was expecting (actually, it was - but you know what I mean). Now for anyone who's done web application development, managing the HTTP Session for these scenarios can be a nightmare. Let's see how easily the Seam framework addresses this all too common problem. If you'd like to produce and fix this problem yourself, continue with the following Steps. If you just want to see the solution, jump to Step 3: Solving the Conversation Problem.

Step 1: Getting the Goods

  • Download NetBeans 5.5
  • Download and extract JBoss Seam 1.0.1 GA
  • Download and install JEMS 1.2.0. BETA1. The JEMS installer includes JBoss AS 4.0.4GA and EJB3 CR8, both of which are needed to work with Seam 1.0.1 GA. Be sure to select the ejb3 profile during installation. Note, if you use the JEMS 1.2.0 BETA2 or 3, you may run into this issue.
  • Download and extract the Registration application.

Step 2: Setting Up Your Environment

In this first step, we'll set up the environment to run our Registration application.

Add the JBoss Server to NetBeans
  1. Switch to the Runtime tab and right-click the Servers node to add a server.



  2. Select JBoss Application Server 4 from the Server drop down list. Change the name to JBoss Application Server 4.0.4.



  3. Complete the Add Server wizard.
  4. Right-click the new JBoss server node and choose Start:

Create the Seam Libraries

The Registration Project that we'll open in the next step references a class library called JBossSeam, which we'll now create using the 1.0.1 GA of Seam:

  1. Open the Library Manager (Tools menu) and create a new class library called JBossSeam.
  2. Set the Classpath to jboss-seam.jar.
  3. Set the Sources to the JBoss Seam src\main directory.
  4. Set the Javadoc to the JBoss Seam doc directory.

These libraries are now available for use by any project.

Open the Registration Project

The Registration application is a NetBeans Enterprise Application Project, which is actually comprised of 3 projects: Registration, Registration-EJBModule and Registration-WebModule. Registraiton-EJBModule and Registration-WebModule are Java EE Modules of the Registration project. Registration-EJBModule generates the EJB jar file. Registration-WebModule generates the war file and Registration generates the ear file which contains the jar and war.

  1. Open the Registration project. The Enterprise Application Project stores the absolute location to its Java EE Modules. So, unless you extracted your project to the exact same location as me, you will see this dialog when you open the project.



  2. Click Close. The Registration project will be in bold red.
  3. Right click the project and select Resolve Reference Problems from the context menu.



  4. Use the Resolve Reference Problems dialog to map each module to its project, which you'll find are subdirectories beneath the Registration directory.

  5. After the references are resolved, right-click the Registration project and select Open Required Projects (now that the dependencies are correct, these dependent projects will always open for you).



  6. You'll notice the Registration-WebModule also has a reference problem, as it references the Registration-EJBModule. Use the same steps to correct the reference.
Test Run the Registration Project
  1. Press F6 to run the project. This will build, package, deploy, start JBoss and launch the application in a browser for you.



    You can now walk through to steps outlined in the introduction to create the "conversation problem".

Step 3: Solving the Conversation Problem

The Registration application in the example is already using Seam, it's just not using the conversation feature. In this step, we'll make a few simple changes to our application which will solve the conversation problem outlined in the introduction.

  1. User is a named seam component that's currently set to session scope, which matches the standard JSF session scope. Open User.java and change the ScopeType from SESSION to CONVERSATION. This will cause Seam to look for @Begin and @End tags to manage the conversation.
    @Scope(ScopeType.CONVERSATION)
  2. Open RegisterActonBean.java and add the @Begin annotation to the confirm method and the @End annotation to the register method. It's as simple as that. The Seam framework will now create and manage a new instance of our User component for each conversation.
        @Begin
        public String confirm() {
            return "success";
        }
        
        @End
        public String register() {
    
  3. Walk through the scenario presented in the introduction above and notice how session data no longer crosses tab (or browser instance) boundaries.




Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds