Struts2 Map Form to Collection of Objects

The Struts2 documentation contains examples that are often basic at best which can make it challenging to figure out how to do things sometimes. I was working on creating a form that would allow me to select values from a list to connect 2 objects in a One-to-Many relationship. This is a common relationship for many things. In this example, I’ll use a User and Role class to demonstrate the concept.

For background, here’s a JPA mapped User and Role class.

import java.util.List;
import javax.persistence.*;
 
@Entity
public class User {
 
    private Long id;
    // ... other member variables
    private List<Role> roles;
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    @OneToMany
    @JoinTable(name = "UserRoles",
            joinColumns = @JoinColumn(name = "user_Id"),
            inverseJoinColumns = @JoinColumn(name = "role_Id"),
            uniqueConstraints = @UniqueConstraint(columnNames = {"user_Id", "role_Id"})
    )
    public List<Role> getRoles() {
        return roles;
    }
 
    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
 
    // ... other properties
}
 
@Entity
public class Role {
 
    private Long id;
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    // ... other properties
}

A list of Roles exists in the database. When a User is created, they are assigned one or more Roles. The User and Roles are connected in the Database through a join table as defined in the mapping. At this point I created some DAO Repository classes to manage the persistence and an Action to handle the form values. (The details of JPA, setting up Persistence and Actions are beyond the scope of this post.)

The part that caused me the most grief ended up being the form. I wanted to add a checkbox list that contained all of the Roles. The example on the Struts site for checkboxlist, a control with 43 documented properties is:

<s:checkboxlist name="foo" list="bar"/>

Needless to say, there was some ‘figuring out’ to be done.

The form itself is pretty vanilla for the most part. The checkboxlist is the interesting part because it’s what allows us to map the User to the Roles. I knew that I was looking for something to put into the value property of the control that would tell it to pre-select the Role values that were already associated with the User.

I started out with something like:

<s:checkboxlist name="user.roles.id"
                    list="roles"
                    listKey="id"
                    listValue="name"
                    label="%{getText('label.roles')}"
                    value="user.roles"/>

That didn’t work. When you think about it, that makes sense because the keys in the list are ids and the values supplied are Role objects. So I needed to figure out how to get the Ids from the Roles. I could have done that in the Action class, but it seemed like there should be a better way. A way that would allow me to continue in more of a Domain fashion.

Doing some research into OGNL, I came upon the list projections section which was the key…

The OGNL projection syntax gives us user.roles.{id}. Basically that is a list comprehension that takes of list of Role objects and turns it into a list of Role Ids. That list of Ids becomes the list of values that will be preselected.

Knowing that I can now create a select box that will include the pre-selected values on an edit form:

<s:checkboxlist name="user.roles.id"
                    list="roles"
                    listKey="id"
                    listValue="name"
                    label="%{getText('label.roles')}"
                    value="user.roles.{id}"/>

Enjoy.

Tags: , , , ,

No Comments

Password Strength Validation with Regular Expressions

Regular Expressions are both complex and elegant at the same time. They can be made to look like someone was just randomly hammering on their keyboard. They are also an incredibly efficient and elegant solution to describing the structure of text and matching those structures. They are very handy for defining what a string should [...]

Tags: ,

No Comments

Scala and Adding New Syntax

One interesting thing about some languages is their support for adding new syntax. While all languages have the ability to add new functions or types some have specific properties that make it easy to add what looks like new built-in syntax.
Scala is an Object Oriented language. You can declare classes and objects, do inheritance and [...]

Tags: , , ,

14 Comments

Grails Embedded Classes ClassCastException

Using ORM tools allow you to map the data to a database independently of how your object model looks. Grails supports one-to-many and one-to-one relationships if you want to have the data in different table. But what about when you want to map a single table to multiple objects? In Grails a has a relationship [...]

Tags: , ,

4 Comments

Update Table Data in Grails using Ajax Calls

Using Ajax for simple forms can offer users a very clean, simple and fast way to input data. I came across a situation recently where I was looking into replacing a document based workflow with an application. The documents themselves contained a series of different kinds of transactions that could have occurred. There were not [...]

Tags: , ,

1 Comment

Using Quartz.NET, Spring.NET and NHibernate to run Scheduled Tasks in ASP.NET

Running scheduled tasks in web applications is not normally a straightforward thing to do. Web applications are built to respond to requests from users and respond to that request. This request/response lifecycle doesn’t always match well to a long running thread that wakes up to run a task every 10 minutes or at 2 AM [...]

Tags: , , , ,

1 Comment

Using Ruby Subversion Bindings to Create Repositories

Subversion has a default Web UI that is served up by Apache if you run Subversion that way. It is pretty boring and read-only. Then there are things like WebSVN that make it less boring, but still read-only. I got curious about what it would take to make something even less boring and NOT read-only. [...]

Tags: , ,

No Comments

DRY your CruiseControl.NET Configuration

Don’t Repeat Yourself (DRY) is one of the principles of good software development. The idea is that there should ideally be one and only one “source of knowledge” for a particular fact or calculation in a system. Basically it comes down to not copying-and-pasting code around or duplicating code if at all possible. The advantages [...]

Tags: , ,

No Comments

StringBuilder and my Biggest Pet Peeve

What You Should Know About Strings
In both Java and .NET (and other languages) String objects are immutable. They don’t change. Period. If you “change” a String, it creates a new String. That includes String concatenation using a +

// One string created "foo"
String foo = "foo";
// foo exists, "bar" is created and the combination of foo [...]

Tags: ,

5 Comments

MSBuild Task for PartCover

<![Rant[
I continue to lament the dearth of option for Test Coverage in the .NET world.
In the Java world you have open source tools like Emma and Cobertura that are widely used and supported (and many more) as well as proprietary tools like Clover available.
.NET we have an open source NCover SF that requires you to [...]

Tags: , , ,

8 Comments