Archive for the ‘Java’ Category

Java Reflection and Introspection example, Populating Dojo Filtering Selects.   2 comments

Reflection and Introspection are advanced java topics  used when building J2EE frameworks.  Often new developers find it difficult to understand what reflection is all about.  In this example I will show off a very basic example of reflection used to reduce boiler plate code for populating Dojo filtering selects. This also has the side affect of keeping the front end in an easy to understand consistent format that allows one to always set the dijit’s label=”label” and value=”value”.

First we should take a look at how to create a Dojo Filtering select. In this case we will generate it programmatically and attach it do a placeholder dom node that would exist in a JSP file.  The key thing here is that a filtering select has both a value and label for each item it contains.  We will populate the filtering select using a Memory Store to hold the JSON data.

  1. First we create the filtering select and replace an existing dom node with it.
  2. We create a method that will make an ajax call to populate the memory store and then assign the store to the filtering select.
  3. In this case the method returns a promise such that we can chain other events to it.

This code will generate a filtering select and replace an existing dom node with the newly created dojo.form.filteringselect
*note this code exists within a dojo module so it is only partial source. We will call the module

 var stateDropdown = new FilteringSelect({
        id: "states",
        // the text to appear in the filtering select dropdown that has no value
        placeHolder:"Select an Option",
        style : "width: 35em",
       	// the attribute the filtering select will use to auto complete the value
        searchAttr: "label",
        labelAttr: "label",
        // the attribute that will display in the dropdown
        itemLabel: 'label',
        // the attribute that will be recorded when a value is selected
        itemValue: 'value',
	// the name of the property that will be submitted with the form.
        name: "state",
        disabled: true
      }, dom.byId("IDofTheTargetDomNodeToReplaceGoesHere"));

Then we will create a dojo xhr (ajax) call to populate the filtering select above. *Note the code isn’t much but my comments are verbose.

   function populateStates() {
       // using the deferred as a promise for chaining events
           var aPromise = new Deferred();
               var stateDropdown = dijit.byId("states");
           // Creating an animation to let the user know the form is still loading.
           var standby = new Standby({target: domAttr.get(stateDropdown.domNode, 'id')});
           document.body.appendChild(standby.domNode);
           standby.startup();
           standby.show();
 
           // create the xhr ajax call to the server 
           xhr(populateStatesUrl, {
               handleAs: 'json',
                   query: {    country : "USA" }
             }).then(function(resp) {
             // if your using dojo 1.6 you may need to wrap this memory store in an object store.
             // this creates a new dojo memory store that will contain data from the json response 
             // and assignes it to the widget
               stateDropdown.set('store',new MemoryStore({
                               data: resp,
                               idProperty: "value"
               }));
           // let the user know we are finished populating the dropdown.
           standby.hide();
               // resolve the promise when we are finished populating the filtering select.  
               // This will chained method calls to execute.
           aPromise.resolve(true);
           });
           return aPromise;
       }

It might be helpful to understand what the JSON should look like that will be stored in the memory store.  Basically it just needs to be an array of object items with key value pairs.

[
    {
        "name": "Alabama",
        "abbreviation": "AL"
    },
    {
        "name": "Alaska",
        "label": "AK"
    },
    {
        "label": "American Samoa",
        "value": "AS"
    },
    {
        "label": "Arizona",
        "value": "AZ"
    },
    {
        "label": "Arkansas",
        "value": "AR"
    },
    {
        "label": "California",
        "value": "CA"
    },
    {
        "label": "Colorado",
        "value": "CO"
    },
    {
        "label": "Connecticut",
        "value": "CT"
    },
    {
        "label": "Delaware",
        "value": "DE"
    },
    {
        "label": "District Of Columbia",
        "value": "DC"
    },
    {
        "label": "Federated States Of Micronesia",
        "value": "FM"
    },
    {
        "label": "Florida",
        "value": "FL"
    },
    {
        "label": "Georgia",
        "value": "GA"
    },
    {
        "label": "Guam",
        "value": "GU"
    },
    {
        "label": "Hawaii",
        "value": "HI"
    },
    {
        "label": "Idaho",
        "value": "ID"
    },
    {
        "label": "Illinois",
        "value": "IL"
    },
    {
        "label": "Indiana",
        "value": "IN"
    },
    {
        "label": "Iowa",
        "value": "IA"
    },
    {
        "label": "Kansas",
        "value": "KS"
    },
    {
        "label": "Kentucky",
        "value": "KY"
    },
    {
        "label": "Louisiana",
        "value": "LA"
    },
    {
        "label": "Maine",
        "value": "ME"
    },
    {
        "label": "Marshall Islands",
        "value": "MH"
    },
    {
        "label": "Maryland",
        "value": "MD"
    },
    {
        "label": "Massachusetts",
        "value": "MA"
    },
    {
        "label": "Michigan",
        "value": "MI"
    },
    {
        "label": "Minnesota",
        "value": "MN"
    },
    {
        "label": "Mississippi",
        "value": "MS"
    },
    {
        "label": "Missouri",
        "value": "MO"
    },
    {
        "label": "Montana",
        "value": "MT"
    },
    {
        "label": "Nebraska",
        "value": "NE"
    },
    {
        "label": "Nevada",
        "value": "NV"
    },
    {
        "label": "New Hampshire",
        "value": "NH"
    },
    {
        "label": "New Jersey",
        "value": "NJ"
    },
    {
        "label": "New Mexico",
        "value": "NM"
    },
    {
        "label": "New York",
        "value": "NY"
    },
    {
        "label": "North Carolina",
        "value": "NC"
    },
    {
        "label": "North Dakota",
        "value": "ND"
    },
    {
        "label": "Northern Mariana Islands",
        "value": "MP"
    },
    {
        "label": "Ohio",
        "value": "OH"
    },
    {
        "label": "Oklahoma",
        "value": "OK"
    },
    {
        "label": "Oregon",
        "value": "OR"
    },
    {
        "label": "Palau",
        "value": "PW"
    },
    {
        "label": "Pennsylvania",
        "value": "PA"
    },
    {
        "label": "Puerto Rico",
        "value": "PR"
    },
    {
        "label": "Rhode Island",
        "value": "RI"
    },
    {
        "label": "South Carolina",
        "value": "SC"
    },
    {
        "label": "South Dakota",
        "value": "SD"
    },
    {
        "label": "Tennessee",
        "value": "TN"
    },
    {
        "label": "Texas",
        "value": "TX"
    },
    {
        "label": "Utah",
        "value": "UT"
    },
    {
        "label": "Vermont",
        "value": "VT"
    },
    {
        "label": "Virgin Islands",
        "value": "VI"
    },
    {
        "label": "Virginia",
        "value": "VA"
    },
    {
        "label": "Washington",
        "value": "WA"
    },
    {
        "label": "West Virginia",
        "value": "WV"
    },
    {
        "label": "Wisconsin",
        "value": "WI"
    },
    {
        "label": "Wyoming",
        "value": "WY"
    }
]

Onto the backend code. There’s many ways to create the required JSON data in the backend. I like Jackson and REST so we for this example assume those technologies are being used in a rest services to handle the front end’s ajax call. The object returned from the rest service will be converted to a JSON representation automatically for us. The Objects returned to populate dropdowns will be lists of labels and values.

In order to generate JSON like the example above, such an item in the list would look something like this.

Pretty simple right? The annoying thing is populating a list of these objects using properties from other POJOS. What we want to do is create something using reflection and introspection that will handle this conversion for us. So we will use generics and create an object that contains a list of objects that have “value” and “label” members. This object will generate it’s own list based on the type of list you pass in, and the member variables names you want to map to “value” and “label”.

Now onto the Java Reflection and Introspection and Generics. We will create a class of a generic class called DropDownListBean that contains a list of the DropDownItemBeans which hold the key value pairs. The constructor for this object will take in a list of any type, along with the names of the properties that we want to use to map the “value” and “label” to. The class will use reflection to create method calls and populate it’s own list of items with “value” and “label” members.
(its internal list of DropDownItemBeans).

The method call to create the DropDownBean would look something like this:

DropDownBean<State> stateDropDownBean = new DropDownBean<>(stateList, abbreviation, fullName);

Where the state objects in teh stateList (not shown) have member variables “private String abbreviation;”, and a getter methods “public String getAbbreviation()… “, as well as member variables “private String fullName;” and methods “public String getFullName()…” Basically any object that follows the JavaBean standards should work. (With the exception of boolean methods which start with ‘is’)

This allows us to create a list of objects that can be used to populate a Dojo MemoryStore in one line assuming the rest service would do the object to json conversion for you, and that the rest service returns DropDownBean.getDropDownItems();

Advertisements

Posted March 7, 2014 by javasavy in Dojo, Java, Javascript, Programming

Always Programming to an interface.   Leave a comment

Programming to an interface is often useful and a very common design pattern.  It can make it easier to change code and create different implementations in the future, minimizing impacts to a current implementation.  From my experience though, programming to an interface just to program to an interface is overkill, overkill, overkill.  A project I recently started working on uses interfaces for many objects in the system including JPA objects.

When using JPA it’s quite common for one object to contain a collection of another object. This composition is key to having an easy to work with data model.  However JPA does not specifically care bout implementing interfaces. in fact JPA annotations should not be used on interfaces. Having all of your JPA model objects programmed to an interface can be a little tricky to deal with.

Note the setter for hammers in WorkerImpl.java. We have to check the type of one of the elements in the list to see if the Cast is safe to do.

We want to make the list of hammers accessible to all of the child classes of Worker, and we must override this method since it exists in the parent class. For example, we want to program an adapter to convert some child class of worker into an xml bean to pass into a form. We don’t necessarily care about the implementation of of the hammer or the worker who owns them, perhaps we have many different implementations of one or both of these. We do however need access to the description of the hammer for whatever type of worker that gets passed into the method. The code above will allow us to parse through the list of hammers for a worker and pull the description.

Posted August 27, 2013 by javasavy in Java, Programming

Assigning Form query parameters to JS variables using EL instead of scriptlets.   Leave a comment

Scriptlets are against my moral fibers, but people still insist on using them like it’s 2002. Liferay is still currently FULL of them as well. One thing I often find myself doing is mapping properties to JS variables.

Posted August 22, 2013 by javasavy in Java, Javascript

1.6 Dojo Grid Selection with xhr Post To Liferay 6.0.6 Portlet   Leave a comment

Spent some time trying to figure out how to post to a Liferay portlet. Although it’s not inherently difficult it can be if you have never done it before and are still learning all about portlets. I really prefer doing this kind of thing using Spring 3 MVC, or restful services, but in this case it really was not an option due to requirements to keep dependencies on external libraries and other modules at a minimum. Code is not complete but it should get the point across. Plus I wanted to test embedding a Gist.

Posted August 22, 2013 by javasavy in Dojo, Java, Javascript, Liferay

JPA 2.0 Mapping Many to Many   Leave a comment

As with many things there is often more than one way to accomplish a task in code.  The example below demonstrates a simple example of how to map a many to many relationship using JPA 2.0, followed by a slightly more complex but more flexible way to do the same thing..

First things first though. It is important to understand how relationships work in JPA. The direction of the relationship is very important. When you annotate a property within a Java Class with @ManyToOne you are stating that the class object’s table can have multiple entries for a single object property you are placing the annotation on within the class. However since your putting the annotation on the property, you might think it would work the other way around. Stop! Soak that in! I will try to provide examples below.

For this example we will create a bi-directional relationship between a system user and an organization. This means that a user may belong to any number of organizations, and organizations contain many users. It requires an association table (join table) to keep track of the relationships.

On the database side the tables would look something like this :

USER
USER_ID USERNAME JOB_TITLE
12345 JoeBob Guru
ORGANIZATION
ORGANIZATION_ID ADDRESS NAME
56789 somewhere in the octagon Initech

And this association / join table to keep track.   (Typical Convention is “OwningTableName” _ “InverseEntityTableName”), but we will show the relationship using the JoinTable annotation so any table name will suffice.  We will also specify the column names in the join table such that default/standardized naming will not be required.

* For example, if default column names are used in the join table and the default table name is correct it can be as simple as adding the annotation @ManyToMany on the owning side (USER in this case) and @ManyToMany(mappedBy = “users”) on the inverse side (ORGANIZATION in this case).

USER_ORGANIZATION
USER_ID ORGANIZATION_ID
12345 56789
@Entity
@Table(name="ORGANIZATION", schema = "MY_SCHEMA")
public class Organization implements Serializable{

	@Id
	@Column(name = "ORGANIZATION_ID")
	private String organizationId;

	// keeping the example simple we wont create an address object
	@Column (name = "ADDRESS")
	private String address;

	@Column (name = "ORG_NAME")
	private String name;

	//bi-directional many-to-many association to USER
	@ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinTable(name="USER_ORGANIZATION", schema = "TABLE_MASTER",
		joinColumns = {@JoinColumn(name="ORGANIZATION_ID")},
		inverseJoinColumns = {@JoinColumn(name="USER_ID")}
	)
	private Set users;

	public String getOrganizationId() {
		return organizationId;
	}

	public void setOrganizationId(String organizationId) {
		this.organizationId = organizationId;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getUsers() {
		return users;
	}

	public void setUsers(Set users) {
		this.users = users;
	}

}
package jpa;

@Entity
@Table(name="USER", schema = "MY_SCHEMA")
public class User implements Serializable{

	@Column(name="USER_ID")
	@Id
	private String userId;

	@Column(name="USERNAME")
	private String username;

	@Column (name="JOB_TITLE")
	private String jobTitle;

	// LAZY tells the class to only load the list if it is acessed within the transaction.
	// We also want the elements in the association table to be removed if the user is deleted.
	@ManyToMany (cascade=CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinTable(name ="USER_ORGANIZATION", schema = "MY_SCHEMA",
			joinColumns = {@JoinColumn(name="USER_ID")},
			inverseJoinColumns = {@JoinColumn(name="ORGANIZATION_ID")}
	)
	private Set organizations;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getJobTitle() {
		return jobTitle;
	}

	public void setJobTitle(String jobTitle) {
		this.jobTitle = jobTitle;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public Set getOrganizations() {
		return organizations;
	}

	public void setOrganizations(Set organizations) {
		this.organizations = organizations;
	}

}

And life is good! We don’t even need to really understand the direction of the relationship since we annotated @ManyToMany. At least for a moment anyways. But then your clever coding buddy tells you you should make this system more robust and there is a problem with what you have done. Here you thought you had solved everything on the first try and were happy using @ManyToMany because it made life so simple.

Suppose instead that Joe Bob is a man of many talents. What happens if he holds different job titles for different companies at the same time? The job title property would then need to be owned by the relationship table / entity bean rather than stored under the user object. Our mapping above will not do at all! This new relationship doesn’t seem all that more complex, but how can we fix this since we have no entity object for the association table? The new tables would look like this:

USER
USER_ID USERNAME
12345 JoeBob
ORGANIZATION
ORGANIZATION_ID ADDRESS NAME
56789 Somewhere in the octagon Initech
efgh Northern California Russian River

And this association / join table to keep track.

USER_ORGANIZATION
USER_ID ORGANIZATION_ID JOB_TITLE
12345 56789 Java Guru
12345 efgh MASTER_BREWER

So instead we need to create an entity for the association table, and an entity that will map to the composite key which identifies the properties that will make up the primary key in the association table.

@Embeddable
public class OrganizationUserPk implements Serializable {

	private static final long serialVersionUID = 1L;

	private String aUserId;

	private String anOrganizationId;

	public OrganizationUserPk(){}

    /* Constructor should create the composite primary key */
	public OrganizationUserPk(String userId, String organizationId){
		this.aUserId = userId;
		this.anOrganizationId = organizationId;
	}

	public String getaUserId() {
		return aUserId;
	}

	public void setaUserId(String aUserId) {
		this.aUserId = aUserId;
	}

	public String getAnOrganizationId() {
		return anOrganizationId;
	}

	public void setAnOrganizationId(String anOrganizationId) {
		this.anOrganizationId = anOrganizationId;
	}

}
/**
 * This entity is created to represent the association table relationship between the user and the organization
 * @author Javasavy
 *
 */
@Entity
@Table(name="ORGANIZATION_USER", schema = "MY_SCHEMA")
public class OrganizationUser implements Serializable {

    private static final long serialVersionUID = 1L;

	@EmbeddedId
	private OrganizationUserPk organizationUserPk;

	@ManyToOne
	@JoinColumn(name = "USER_ID", nullable = false, insertable = true, updatable = true)
	// Although I might use "userId" for @MapsId in the real world I want to be clear the that mapsId refers to the
	// property in the OrganizationUserPk object, not the userId in the User.java class.  JPA will automagically look for
	// and use the @Id annotated property in the User.java class when resolving this mapping.
	@MapsId("aUserId")
	private User user;

	@ManyToOne
	@JoinColumn(name = "ORGANIZATION_ID", nullable = false, insertable = true, updatable = true)
	@MapsId("anOrganizationId")
	private Organization organization;

	@Column (name="JOB_TITLE")
	private String jobTitle;

	/* Constructor */
	public OrganizationUser (User user, Organization organization, String jobTitle){
		this.user= user;
		this.organization = organization;
		this.jobTitle = jobTitle;
	}

	public OrganizationUserPk getOrganizationUserPk() {
		return organizationUserPk;
	}

	public void setOrganizationUserPk(OrganizationUserPk organizationUserPk) {
		this.organizationUserPk = organizationUserPk;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Organization getOrganization() {
		return organization;
	}

	public void setOrganization(Organization organization) {
		this.organization = organization;
	}

	public String getJobTitle() {
		return jobTitle;
	}

	public void setJobTitle(String jobTitle) {
		this.jobTitle = jobTitle;
	}
}
@Entity
@Table(name="USER", schema = "MY_SCHEMA")
public class User implements Serializable{

    private static final long serialVersionUID = 1L;

	@Id
	@Column(name="USER_ID")
	private String userId;

	@Column(name="USERNAME")
	private String username;

	// mappedBy refers to the "user" member variable within OrganizationUser.java class, however remember that we are Stating
	// that there can only be multiple OrganizationUser entries for a single user by marking it as @OneToMany
	// (One table row in USER, can have multiple rows in the table mapped my OrganizationUser: ORGANIZATION_USER
	// we set orphanRemoval to true so that if the User is deleted all orphans in the ORGANIZATION_USER table
	// will also be removed.
	@OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval=true)
	private Set organizationUsers;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public Set getOrganizationUsers() {
		return organizationUsers;
	}

	public void setOrganizationUsers(Set organizationUsers) {
		this.organizationUsers = organizationUsers;
	}
}
@Entity
@Table(name="ORGANIZATION", schema = "MY_SCHEMA")
public class Organization implements Serializable{

    private static final long serialVersionUID = 1L;

	@Id
	@Column(name = "ORGANIZATION_ID")
	private String organizationId;

	// location keeping the example simple we wont create an address object
	@Column (name = "ADDRESS")
	private String address;

	@Column (name = "ORG_NAME")
	private String name;

	@OneToMany(mappedBy = "organization", cascade=CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval=true)
	private Set organizationUsers;

	public String getOrganizationId() {
		return organizationId;
	}

	public void setOrganizationId(String organizationId) {
		this.organizationId = organizationId;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getOrganizationUsers() {
		return organizationUsers;
	}

	public void setOrganizationUsers(Set organizationUsers) {
		this.organizationUsers = organizationUsers;
	}
}

Life is good once again, and Joe Bob gets to continue on with his life as a Java Guru and Master Brewer!
One thing to note is that the above configuration does NOT support having two different jobs / job titles at the same organization! If we wanted to do that we would probably want break out the job title description into a seperate table with an appropriate primary key, then use this new primary key in the association table in place of the job_title description. It would also require new mappings in the entities. The Composite Pk object would then consist of userId, OrganizationId, and jobTitleId.

Posted August 22, 2013 by javasavy in Java, Programming