CDI Instance Injections and Session/Application Scoped Beans

If you’ve spent much time with CDI you invariably had a use case where you would prefer not to trigger an injection when the bean is initialized. This can be handy for example if it is an expensive action and the injected bean is only going be be invoked a small percentage of the time.

There is however caveat that is relevant. The beans produced by the Instance will live until the containing bean is destroyed.

This doesn’t cause an issue with Dependent, Request, View, or Conversation scoped beans, but it would cause a unexpected memory leak with Application or even Session scoped beans. Since the Instance could be invoked multiple times spanning hours or days with a @SessionScoped bean and potentially weeks or months with an @ApplicationScoped bean (if your lucky to run your app uninterrupted that long) the memory leak could bring your app to a halt.

Improvement are being made to the CDI 1.1 spec to handled this better CDI-139

But in the meantime the following will work nicely

@Inject
    BeanManager bm;
    
    public void run() {
    
      CreationalContext<Foo> ctx = bm.createCreationalContext(null);
      Bean<?> beans = BeanManagerTools.beans(bm, Foo.class);
      Foo f = bm.getReference(beans, Foo.class, ctx);
    
      //Do Work
    
      ctx.release();
    }

Calling the release at the end destroys all the beans created in the Context we initialized (ctx)

tags: java cdi
Cody Lerum - December 16, 2011

Sorting Java Enums

Occasionally when working with JSF I have the need to display the values of a Java Enum in a pick-list.

public enum Cars {
      KIA,
      BMW,
      TOYOTA,
      FERRARI
    }

Returning an array of these values is easy enough. Cars.values();

The ordering of the values in the array is set by the ordinal value of the enum, or more simply the order which it appears in the source code. {"KIA", "BMW", "TOYOTA", FERRARI"}

Now depending on your application, if you need to change the order you can simply change the order they appear in the source code. However if you are like me and persisting these values to a database based on their ordinal value to save space then changing the order will break your application.

@NotNull
    @Column(columnDefinition = "tinyint")
    @Enumerated(EnumType.ORDINAL)
    public Cars getCar() {
      return car;
    }
    
    public void setEgressCodec(Cars car) {
      this.car = car;
    }

The first thing you might want to do is implement Comparable on the Enum and override the compareTo with your own to control the ordering. Unfortunately compareTo() is final on the Enum so we can’t override it.

Here is the solution that I’ve come up with.

First I create a new interface called ComparableEnum

ComparableEnum.java

public interface ComparableEnum {
      public String getDisplayName();
      public int getPriority();
      public boolean isDisplayed();
      public int ordinal();
    }

Then I can implement this on my Cars Enum using the cost a car as a value for the priority

Cars.java

public enum Cars implements ComparableEnum {
    
      KIA("Kia Motors", 15000, true),
      BMW("Bavarian Motor Works", 55000, true),
      TOYOTA("Toyota Motors", 35000, true),
      FERRARI("Ferrari S.p.A.", 150000, true)
    
      private String displayName;
      private int priority;
      private boolean displayed;
    
      private Cars(String displayName, int priority, boolean displayed) {
         this.displayName = displayName;
         this.priority = priority;
         this.displayed = displayed;
      }
      public String getDisplayName() {
         return displayName;
      }
      public int getPriority() {
         return priority;
      }
      public boolean isDisplayed() {
         return displayed;
      }
    }

Now it’s just a matter adding a couple comparators

EnumNameComparator.java

public class EnumNameComparator<T extends ComparableEnum> implements Comparator<T> {
      public int compare(T o1, T o2)
      {
         if (o1.getDisplayName().compareTo(o2.getDisplayName()) != 0){
            return o1.getDisplayName().compareTo(o2.getDisplayName());
         }
         else if (o1.toString().compareTo(o2.toString()) != 0) {
            return o1.toString().compareTo(o2.toString());
         }
         else {
            return new Integer(o1.ordinal()).compareTo(new Integer(o2.ordinal()));
         }
      }
    }

EnumPriorityComparator.java

public class EnumPriorityComparator<T extends ComparableEnum> implements Comparator<T> {
      public int compare(T o1, T o2)
      {
         if (new Integer(o1.getPriority()).compareTo(new Integer(o2.getPriority())) != 0)
         {
            return new Integer(o1.getPriority()).compareTo(new Integer(o2.getPriority()));
         }
         else if (o1.toString().compareTo(o2.toString()) != 0)
         {
            return o1.toString().compareTo(o2.toString());
         }
         else
         {
            return new Integer(o1.ordinal()).compareTo(new Integer(o2.ordinal()));
         }
      }
    }

Now I want to be able to sort these easily using any enum I have which implements Comparable enum so I add a generic method.

private static <T extends ComparableEnum> List<T> getEnumSortedByPriority(T[] t) {
      EnumPriorityComparator<T> c = new EnumPriorityComparator<T>();
      List<T> list = removeNonDispalyedValues(t);
      Collections.sort(list, c);
      return list;
    }

Now I can create a simple method to return my enum sorted how I wish

public static List<Cars> componentTypes() {
      return getEnumSortedByPriority(ComponentType.values());
    }
tags: java
Cody Lerum - May 21, 2010

Composite Primary Key with @ManyToOne

Here is a fun issue that I ran into the other day while working with a legacy database.

Three tables:

Nodes

  • NodeID(pk)

Interfaces

  • InterfaceID(pk)

  • NodeID(fk)

InterfaceTraffic_Detail

  • InterfaceID(pk)

  • DateTime(pk)

  • NodeID(fk)

The InterfaceTraffic_Detail table turned out to be a little tricky for me since I have never worked with composite indexes in hibernate. It took a little trial and error but here is what I came up with

My environment is Hibernate 3.4

NmsNode.java

@Name("nmsNode")
    @Entity
    @Table(name="Nodes")
    public class NmsNode implements Serializable {
      private static final long serialVersionUID = 1462044144509159489L;
    
      private int id;
      private List&lt;NmsInterface&gt; interfaces;
    
      @Id
      @Column(name="NodeID")
      public int getId() {
        return id;
      }
    
      public void setId(int id) {
        this.id = id;
      }
    
      @OneToMany(mappedBy="node", fetch=FetchType.LAZY)
      public List&lt;NmsInterface&gt; getInterfaces() {
        return interfaces;
      }
    
      public void setInterfaces(List&lt;NmsInterface&gt; interfaces) {
        this.interfaces = interfaces;
      }
    }

NmsInterface.java

@Name("nmsInterface")
    @Entity
    @Table(name="Interfaces")
    public class NmsInterface implements Serializable
    {
    
       private static final long serialVersionUID = 1L;
    
       private int id;
       private NmsNode node;
    
    
       @Id
       @Column(name="InterfaceID")
       public int getId()
       {
          return id;
       }
       public void setId(int id)
       {
          this.id = id;
       }
    
       @ManyToOne
       @JoinColumn(name="NodeID")
       public NmsNode getNode()
       {
          return node;
       }
       public void setNode(NmsNode node)
       {
          this.node = node;
       }
    }

InterfaceTraffic_Detail.java

@Entity
    @Table(name="InterfaceTraffic_Detail")
    @AssociationOverrides
       (
          {
               @AssociationOverride(name = "id.nmsInterface",
                     joinColumns = @JoinColumn(name = "InterfaceID"))
          }
       )
    public class InterfaceTraffic_Detail implements Serializable
    {
       private static final long serialVersionUID = 1L;
       private InterfaceTraffic_PrimaryKey id;
       private NmsNode nmsNode;
    
       @EmbeddedId
       @AttributeOverrides
       (
             {
                @AttributeOverride(name="id.dateTime", column=@Column(name="DateTime"))
             }
       )
       public InterfaceTraffic_PrimaryKey getId()
       {
          return id;
       }
       public void setId(InterfaceTraffic_PrimaryKey id)
       {
          this.id = id;
       }
       @ManyToOne
       @JoinColumn(name="NodeID")
       public NmsNode getNmsNode()
       {
          return nmsNode;
       }
       public void setNmsNode(NmsNode nmsNode)
       {
          this.nmsNode = nmsNode;
       }
    }

InterfaceTraffic_PrimaryKey.java

@Embeddable
    public class InterfaceTraffic_PrimaryKey implements Serializable
    {
       private static final long serialVersionUID = 1L;
       private NmsInterface nmsInterface;
       private Date dateTime;
    
       @ManyToOne
       public NmsInterface getNmsInterface()
       {
          return nmsInterface;
       }
       public void setNmsInterface(NmsInterface nmsInterface)
       {
          this.nmsInterface = nmsInterface;
       }
       public Date getDateTime()
       {
          return dateTime;
       }
       public void setDateTime(Date dateTime)
       {
          this.dateTime = dateTime;
       }
    
       public int hashCode() {
          return (int) dateTime.hashCode() + nmsInterface.getId();
      }
    
      public boolean equals(Object obj) {
          if (obj == this) return true;
          if (obj == null) return false;
          if (!(obj instanceof InterfaceTraffic_PrimaryKey)) return false;
          InterfaceTraffic_PrimaryKey pk = (InterfaceTraffic_PrimaryKey) obj;
          return pk.nmsInterface.getId() == nmsInterface.getId() &amp;&amp; pk.dateTime.equals(dateTime);
      }
    }

The important part here is the @EmbeddedId and @Embeddable on the InterfaceTraffic_Detail and InterfaceTraffic_PrimaryKey as well as the name "id.nmsInterface" on the @AssociationOverride so that I could reference the variable on the embedded class and define the @JoinColumn

Hopefully this saves someone else some time.

tags: java hibernate
Cody Lerum - January 12, 2010

JSF 2.0 still lacking support for collections

Unfortunately the freshly minted JSF 2.0 spec still doesn’t support a generic Collection interface. Currently only a List is supported and while this does work for many situations, it does cause many issues when you are working with a full JavaEE stack since it may be necessary to use Set or SortedSet when working with JPA.

It hasn’t been used in the past, but it’s time for the users to start voting on java.net. So go there, register and throw some of your votes towards this painful issue.

tags: java jsf
Cody Lerum - January 04, 2010

Hibernate Optimistic Locking and MySQL

So I ran into a fun little issue the other day while working with MySQL and Hibernate.

Hibernate provides optimistic locking via the Version function. This can either be a numeric field or a timestamp. I use Hibernate Annotations, so for me it simply involves placing the following annotation inside my entity.

private Date dateModified;
    
    @Version
    private Date getDateModified() {
      return dateModified;
    }
    private void setDateModified(Date dateModified) {
      this.dateModified = dateModified;
    }

This worked great for me, and provided both an optimistic lock as well as a dateModified field I could use to show the last time the entity was updated. I should say that this worked great during development while I was using hypersonic as my database. When I deployed to a lab server for testing against our MySQL database I started to run into some OptimisticLockExceptions

After doing some digging around I found out that MySQL doesn’t store date/time with millisecond precision. This is a well known feature request / bug and it doesn’t appear that it will be fixed anytime soon. So I was forced to refactor my code so that the "version" was a int and still maintain a dateModified field since the user interface had made use of it in various places.

Thankfully Hibernate provides Call Back annotations which allow me to trigger an update of the dateModified when a Persist or Update is called. I also used this logic to automatically set the dateCreated field on entities when needed.

I also added an @Deprecated to the setters for dateCreated and dateModified to discourage others from setting those fields manually.

Here is what the final code looks like.

private int version;
    private Date dateCreated;
    private Date dateModified;
    
    @NotNull
    public Date getDateCreated() {
      return dateCreated;
    }
    
    @Deprecated
    public void setDateCreated(Date dateCreated) {
      this.dateCreated = dateCreated;
    }
    
    @PrePersist
    public void updateDateCreated() {
      dateCreated = new Date();
      dateModified = dateCreated;
    }
    
    @NotNull
    public Date getDateModified() {
      return dateModified;
    }
    
    @Deprecated
    public void setDateModified(Date dateModified) {
      this.dateModified = dateModified;
    }
    
    @PreUpdate
    public void updateDateModified() {
      dateModified = new Date();
    }

Update!

It looks like mysql has this on their roadmap and outlines their plans with a fairly extensive worklog. However this is slated for MySQL 6.0 or 7.0 and thus will be a few years out. Maybe it’s time to checkout what PostgreSQL is all about.

Cody Lerum - December 29, 2009
About outjected.com

Outjected is an infrequent blog about the frequent issues and annoyances that pop up while coding.

These are living posts and will be updated as errors or improvements are found.
About Me
Google+