Hibernate lock() to Reattach Detached Objects

Hibernate offers pessimistic locking as an option for concurrency control.  Hibernate?s pessimistic lock is actually a function of the underlying database.  Hibernate does not actually ?lock? objects in memory.  Locks are requested of the database by Hibernate operations like the following:

  • session.get(classType, objectId, lockOptions)
  • session.load(classType, objectId, lockOptions)
  • session.refresh(objectReference, lockOptions)
  • session.buildLockRequest(lockOptions).lock(objectRef)
    • this replaces the now deprecated session.lock(objectRef, lockMode) operations
  • executing query with appropriate setLockOptions(lockOptions) called
  • executing criteria with appropriate setLockOptions(lockOptions) called

For more details on HIbernate pessimistic locking see the documentation here.

Using .lock() to Reattach

The lock() method can be an important operation when looking at pessimistic operations, but it also has another less know use.  The lock() method, with LockOptions.NONE, can be used to associate a detached object to a session and put the object back into a persistence context.  Importantly, it does this without forcing an update of the database (as the update() or saveOrUpdate() method would).  With LockOptions.NONE, it doesn?t get a database lock and it doesn?t even do a version check against the database.  Importantly, changes that have been made to detached object before a call to the lock() method with LockOptions.NONE are not synchronized  to the database.  Therefore, only call lock() on detached objects that you know have not been modified outside of a persistent context.

As an example, look at these two code examples.  On top is Hibernate code to reattach a detached object using a typical update method call.  On the bottom is code to reattach a detached object using a .lock method call.

Update Code
   1: SessionFactory sf = new Configuration().configure()
   2:         .buildSessionFactory();
   3: Session sess = sf.openSession();
   4: Transaction trx = sess.beginTransaction();
   5: Vehicle v = (Vehicle) sess.get(Vehicle.class, 1L);
   6: trx.commit();
   7: sess.close();
   8: System.out.println("vehicle now detached: " + v);
   9:  
  10: //update the vehichle outside of session when detached.
  11: v.setVin(123);
  12:  
  13: //reattach and update
  14: sess = sf.openSession();
  15: trx = sess.beginTransaction();
  16: sess.update(v);
  17: System.out.println("completed the update call");
  18: trx.commit();
  19: sess.close();
  20: System.out.println("vehicle synchronized again: " + v);
Locking Code
   1: SessionFactory sf = new Configuration().configure()
   2:         .buildSessionFactory();
   3: Session sess = sf.openSession();
   4: Transaction trx = sess.beginTransaction();
   5: Vehicle v = (Vehicle) sess.get(Vehicle.class, 1L);
   6: trx.commit();
   7: sess.close();
   8: System.out.println("vehicle now detached: " + v);
   9:  
  10: //update the vehichle outside of session when detached.
  11: v.setVin(678);
  12:  
  13: //reattach using lock
  14: sess = sf.openSession();
  15: trx = sess.beginTransaction();
  16: sess.buildLockRequest(LockOptions.NONE).lock(v);
  17: System.out.println("completed the update call");
  18: trx.commit();
  19: sess.close();
  20: System.out.println("vehicle synchronized again: " + v);
Note: prior versions of Hibernate use sess.lock(v, LockMode.NONE); to perform the same operation as you see with buildLockRequest().lock() above. The .lock() methods have recently been deprecated.

The resulting SQL from each set of operations makes clear that the update() call causes the SQL to execute once the transaction commits (see top). On the other hand, no SQL is issued in the lock() call ? even if the object has indeed changed (see bottom).

SQL resulting from update call
   1: Hibernate: 
   2:     select
   3:         vehicle0_.id as id0_0_,
   4:         vehicle0_.make as make0_0_,
   5:         vehicle0_.model as model0_0_,
   6:         vehicle0_.vin as vin0_0_ 
   7:     from
   8:         Vehicle vehicle0_ 
   9:     where
  10:         vehicle0_.id=?
  11: vehicle now detached: Vehicle [id=1, make=Chevy, model=sedan, vin=345]
  12: completed the update call
  13: Hibernate: 
  14:     update
  15:         Vehicle 
  16:     set
  17:         make=?,
  18:         model=?,
  19:         vin=? 
  20:     where
  21:         id=?
  22: vehicle synchronized again: Vehicle [id=1, make=Chevy, model=sedan, vin=123]
SQL resulting from lock() call
   1: Hibernate: 
   2:     select
   3:         vehicle0_.id as id0_0_,
   4:         vehicle0_.make as make0_0_,
   5:         vehicle0_.model as model0_0_,
   6:         vehicle0_.vin as vin0_0_ 
   7:     from
   8:         Vehicle vehicle0_ 
   9:     where
  10:         vehicle0_.id=?
  11: vehicle now detached: Vehicle [id=1, make=Chevy, model=sedan, vin=345]
  12: completed the update call
  13: vehicle synchronized again: Vehicle [id=1, make=Chevy, model=sedan, vin=678]
Again, you only want to use the lock() operation when you know the detached object has not changed, but this contrived demonstration shows you how lock() can save you SQL/database calls in cases where you know a detached object has not been modified.

Wrap Up

Interested in learning more about Hibernate?  Attend Complete Hibernate at Intertech in person over via our virtual classroom.  Contact Dan McCabe for details.

Posted by: Jim White
Posted on: 12/20/2011 at 11:51 AM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Hibernate Optimistic Lock without a Version (or Timestamp)

Last week, I taught Intertech?s Complete Hibernate to a group of students that already had a bit of experience with Hibernate (on the job training as they took over an existing application).  Because of some of their experiences, they had a number of excellent  and advanced questions.  Some of my upcoming blog posts are answers to some of these questions ? some of which I must admit had me scrambling to the documentation and Hibernate text books for help and background material.  So, before beginning, I must thank Tyler, Jeff and Mike for their observations, keen eye, and desire to fill in the knowledge gaps to some of what they already knew.  Hopefully some of their questions and the answers I provide can help you in your Hibernate work as well.

Hibernate Optimistic Locking

The question I would like to address in this post is about Hibernate optimistic locking ? optimistic locking with no special version number or timestamp.  While pessimistic locking is an available option in Hibernate to address concurrency control, for most enterprise applications, optimistic locking is the preferred choice.  As the Hibernate documentation states:

?The only approach that is consistent with high concurrency and high scalability, is optimistic concurrency control with versioning?

Hibernate can provide optimistic locking via version number or effectivity timestamp.  To learn more about either approach, you can see an earlier post of mine, or check out the Hibernate documentation.   Optimistic locking via version number or effectivity timestamp is automatically managed by Hibernate.  Simply provide the column to hold the version or timestamp, add the optimistic lock characteristics to your Hibernate mapping (via XML or annotations), and Hibernate does the rest.

Optimistic Locking sans Version or Timestamp

However, there may be situations whereby adding a version number or timestamp column to your database table is not possible.  This might be the case when a legacy database is in place and many applications use the table and cannot or will not be updated to use a new version/timestamp column for optimistic locking.  In this case, Hibernate can compare the column values of a table row against the state of the persistent object to check that nothing in a row was modified before updating the row.  There are two forms of this state-checking optimistic locking:  all-state-check or dirty-state-check.

Optimistic-lock = ?all?

When you set the optimistic-lock attribute on the <class> element in the Hibernate mapping file to the value ?all? (as shown on the Vehicle class mapping below), you are informing Hibernate to check that no column in the associated row has changed since the persistent object was retrieved and before updating the row in the database.

   1: <hibernate-mapping package="com.intertech.domain">
   2:     <class name="Vehicle" dynamic-update="true" optimistic-lock="all">
   3:         <id name="id">
   4:             <generator class="increment" />
   5:         </id>
   6:         <property name="make" />
   7:         <property name="model" />
   8:         <property name="vin" />
   9:     </class>
  10: </hibernate-mapping>

For example, say you used Hibernate to obtain an instance of Vehicle and then updated it?s make as shown by the code below.

   1: SessionFactory sf = new Configuration().configure()
   2:         .buildSessionFactory();
   3: Session sess = sf.openSession();
   4: Transaction trx = sess.beginTransaction();
   5: Vehicle v = (Vehicle) sess.get(Vehicle.class, 1L);
   6: v.setMake("Kia");
   7: sess.saveOrUpdate(v);
   8: trx.commit();
   9: sess.close();

Hibernate would actually use all the existing persistent object values (the last known state values) to form the SQL where-clause used in the update call.  Note that every column is mentioned in the where-clause of the example, even the old value of the changed property (make in this case).  If any other concurrent activity on this row changed the data of the row (or deleted the row), Hibernate would detect this by the fact that the where-clause would fail to match the row (resulting in a StaleObjectStateException.

   1: Hibernate: 
   2:     update
   3:         Vehicle 
   4:     set
   5:         make='Kia' 
   6:     where
   7:         id=1
   8:         and make='Ford' 
   9:         and model='SUV'
  10:         and vin=12345

Optimistic-lock = ?dirty?

As an alternative, you can also allow Hibernate to only use modified or dirty properties in the where-clause of the update.  When mapping the persistent class, set the optimistic-lock attribute to a value of ?dirty? (as shown below).

   1: <hibernate-mapping package="com.intertech.domain">
   2:     <class name="Vehicle" dynamic-update="true" optimistic-lock="dirty">
   3:         <id name="id">
   4:             <generator class="increment" />
   5:         </id>
   6:         <property name="make" />
   7:         <property name="model" />
   8:         <property name="vin" />
   9:     </class>
  10: </hibernate-mapping>

Hibernate now uses only the last known state values of modified persistent object properties to form the SQL where-clause used in the update call.  As an example, assume this code is used to update a Vehicle?s make and model state.

   1: SessionFactory sf = new Configuration().configure()
   2:         .buildSessionFactory();
   3: Session sess = sf.openSession();
   4: Transaction trx = sess.beginTransaction();
   5: Vehicle v = (Vehicle) sess.get(Vehicle.class, 1L);
   6: v.setMake("Chevy");
   7: v.setModel("sedan");
   8: sess.saveOrUpdate(v);
   9: trx.commit();
  10: sess.close();

The update SQL only includes checks of the existing row?s make and model columns ? that is the dirty properties.

   1: Hibernate:
   2:     update
   3:         Vehicle 
   4:     set
   5:         make='Chevy',
   6:         model='sedan' 
   7:     where
   8:         id=1 
   9:         and make='Kia' 
  10:         and model='SUV'

This alternative allows other concurrent processes to update the same row so long as they do not modify the same columns.  For example, another application could be updating the vin number of our vehicle at the same time we are updating the make and model and neither of the applications suffer a concurrency error.  The merits of allowing this type of simultaneous update are questionable (at best).  From a business perspective, only you can determine if modifications that do not conflict constitute change that should cause a concurrency failure or not.  Hibernate provides the options, you must determine whether the technology fits with your definition of protecting against concurrent change issues.

Dynamic-update must be True

It should be noted that in both of these non-version/timestamp optimistic locking options, you must enable dynamic-update (set the dynamic-update='?true? attribute) in the class mapping as shown above.  This is because Hibernate cannot generate the SQL for these update statements at application startup (it wouldn?t know what to include in the update statement where-clauses until a change is actually made).

Big Limitations of Non-Version/Timestamp Optimistic Locking

Regardless of whether you use the optimistic-lock=all or optimistic-lock=dirty strategy, there are some big limitations to Hibernate?s optimistic locking that does not use version numbers or timestamps.

No Detached

When you close a session, Hibernate loses its persistence context and ability to track what changes on the objects.  Therefore, you cannot use the optimistic-lock=all or optimistic-lock=dirty option unless you retrieve and modify the persistent object in the same session (i.e. persistence context).  If you attempt to get a persistent object in one session, detach the object and then update the object in another session, you will actually create a situation of potentially catastrophic last-in-wins updates.  For example, try this code with optimistic-lock set to ?all? on the Vehicle class mapping.

   1: SessionFactory sf = new Configuration().configure()
   2:         .buildSessionFactory();
   3: Session sess = sf.openSession();
   4: Transaction trx = sess.beginTransaction();
   5: Vehicle v = (Vehicle) sess.get(Vehicle.class, 1L);
   6: trx.commit();
   7: sess.close();
   8: System.out.println("vehicle now detached: " + v);
   9:  
  10: v.setVin(7890);
  11:  
  12: //reattach and update
  13: sess = sf.openSession();
  14: trx = sess.beginTransaction();
  15: sess.saveOrUpdate(v);
  16: trx.commit();
  17: sess.close();
  18: System.out.println("vehicle saved again: " + v);

When Hibernate reattaches the Vehicle object and brings it back into the persistence context in the second session, it actually does the unthinkable ? it synchronizes (i.e. updates) every column of the associated row without checking to see if it was updated by some other concurrent process!  Last in wins and no concurrency check!!!

   1: Hibernate: 
   2:     update
   3:         Vehicle 
   4:     set
   5:         make='Chevy',
   6:         model='sedan',
   7:         vin=7890 
   8:     where
   9:        id=1

Not JPA Standard

Wonder why I haven?t shown you the annotation form of this non-version optimistic locking yet?  If you are currently using annotations to provide all of your object-database mappings, you will also be disappointed to learn JPA does not support optimistic locking outside of versioning (by number or timestamp).  So there are no JPA annotations to perform optimistic locking by field or dirty fields.  There is, however, a Hibernate annotations that can be used.  When mapping, add a parameter to the org.hibernate.annotations.Entity annotation to specify how to perform optimistic locking (as shown here).

   1: @Entity
   2: @org.hibernate.annotations.Entity(dynamicUpdate = true,
   3:         optimisticLock = OptimisticLockType.ALL)
   4: public class Vehicle {
   5:   // ...
   6: }

Of course, this annotation requires a Hibernate import and more tightly couples your domain class to Hibernate.

It?s Slower

Additionally, note that using all-column or dirty-column checks as part of the where-clause is a little slower.  When updating a single persistent object every so often, the speed may not be an issue.  But in systems dealing with large numbers of transactions, every millisecond counts.

Wrap Up

As you can see, Hibernate can perform some real time and code-saving work when it comes to optimistic locking.  The several options allow for you to pick a concurrent strategy in-line with your system architecture and business needs.  But under most circumstances, Hibernate optimistic locking without a version or timestamp will not work for highly concurrent, highly scalable applications ? and doesn?t that pretty much describe most enterprise application needs today?  If you need more help on Hibernate, contact Intertech and consider taking our Complete Hibernate class.


Posted by: Jim White
Posted on: 12/16/2011 at 4:47 PM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Hibernate - Why Are there nulls in my collection?

When using Hibernate, developers are often confused by the appearance of nulls in ?-to-many? collection associations.  This can be particularly confusing since the original object collection did not contain any nulls.  ?Where did the nulls come from??  ?I don?t see anything in the database that would suggest nulls should be created??  ?What?s wrong with Hibernate??  All good questions, but in fact, this is the expected behavior of Hibernate in indexed collection (lists and arrays) mappings.

Indexed Collections Example

In order to understand collection mapping and for purposes of discussion, assume a one-to-many relationship between objects of type Foo and Bar.  In this example, Foo and Bar object state is saved in the same named tables (FOO and BAR) with the foo_id column in the BAR table holding the foreign key to associated instances of Foo in the database.

image          image

In Foo.java, assume a java.util.List holds the collection of associated Bars.  However, the collection could also be held in an array (Bar[ ]) and the same issue can be seen.

   1: public class Foo {
   2:  
   3:     private Long id;
   4:     private String name;
   5:     private List<Bar> bars;
   6:  
   7:     public List<Bar> getBars() {
   8:         return bars;
   9:     }
  10:  
  11:     public void setBars(List<Bar> bars) {
  12:         this.bars = bars;
  13:     }
  14:  
  15:     // rest of the code removed for brevity
  16:  
  17: }

The relationship must be made known to Hibernate through mapping; either using XML or annotations as shown below.

XML mapping
   1: <?xml version="1.0"?>
   2: <!DOCTYPE hibernate-mapping PUBLIC
   3:     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   4:     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
   5: <hibernate-mapping package="com.intertech">
   6:     <class name="Foo">
   7:         <id name="id">
   8:             <generator class="increment" />
   9:         </id>
  10:         <property name="name" />
  11:         <list name="bars" inverse="true">
  12:             <key column="foo_id" />
  13:             <list-index column="length" />
  14:             <one-to-many class="com.intertech.Bar" />
  15:         </list>
  16:     </class>
  17: </hibernate-mapping>
Annotation mapping
   1: public class Foo {
   2:  
   3:     @OneToMany
   4:     @JoinColumn(name="foo_id")
   5:     @org.hibernate.annotations.IndexColumn(name="length")
   6:     private List<Bar> bars;
   7:  
   8:     // rest of the code and annotation removed for brevity
   9: }

Notice that an index column (list-index element in XML or IndexColumn annotation) is provided to inform Hibernate how to index or order the items in the resulting collection of Bars when a Foo object is retrieved.  In this example, the Bar?s ?length? attribute is used to index or order the Bars associated to Foo.  Hibernate requires lists or arrays to be ordered by some available integer value.

image

The Null Problem

Using Hibernate and the mapping shown above, all looks wonderful when saving Foo/Bar objects.  The confusion usually results when retrieving the same objects through code like that below.

   1: SessionFactory sessionFactory = new Configuration()
   2:         .configure()
   3:         .buildSessionFactory();
   4:  
   5: Session s = sessionFactory.openSession();
   6: Transaction trx = s.beginTransaction();
   7:  
   8: Foo f = (Foo) s.get(Foo.class, 1L);
   9: for (Bar bar : f.getBars()) {
  10:     System.out.println(bar);
  11: }
  12:     
  13: trx.commit();
  14: s.close();

Assume a single Foo object (id = 1) is associated to four Bar objects.  Below is a look at the BAR table where the Bar object state is held.

image

Here are the results of running the Foo retrieval code above.  Notice all the nulls?  Where did they come from?  Hibernate adds null elements to the list if the index numbers (in this case the length attribute) are not continuous!  Hibernate assumes by default that the list index starts at 0 and each position in the list is to be filled.  Therefore, because the first index in this case is 3 (the length of Bar with id=1), there are 3 nulls serving as place holders in the list for possible Bar objects at positions 0, 1 and 2.  You?ll also note nulls at positions 5 ? 7, 9, and 11.  Again, place holders for possible Bars with lengths of 4, 5, 6, 8, and 10.

null
null
null
I am a Bar; id = 1 , description:  "this is bar A", and length of:  3
null
null
null
I am a Bar; id = 3 , description:  "this is bar C", and length of:  7
null
I am a Bar; id = 4 , description:  "this is bar D", and length of:  9
null
I am a Bar; id = 2 , description:  "this is bar B", and length of:  11

How to fix it

Yuck you say!  You don?t want these nulls in your list (or array).  What are your options?  First, you can specify a ?base? value in your mapping.  This value specifies the first element of the list or array.  Notice the base attribute on the list-index element and base parameter to the IndexColumn annotation below.

Change to <list> element in XML mapping

   1: <list name="bars" inverse="true">
   2:     <key column="foo_id" />
   3:     <list-index column="length" base="3"/>
   4:     <one-to-many class="com.intertech.Bar" />
   5: </list>

Change to Foo annotation mapping

   1: @OneToMany
   2: @JoinColumn(name = "foo_id")
   3: @org.hibernate.annotations.IndexColumn(name = "length", base=3)
   4: private List<Bar> bars;
This helps, but may not completely resolve the issue.  Now, Hibernate assumes the list or array is to start at the base index so leading nulls are removed, but the nulls that serve as space holders between the first and last indexes are still present.

I am a Bar; id = 1 , description:  "this is bar A", and length of:  3
null
null
null
I am a Bar; id = 3 , description:  "this is bar C", and length of:  7
null
I am a Bar; id = 4 , description:  "this is bar D", and length of:  9
null
I am a Bar; id = 2 , description:  "this is bar B", and length of:  11

As another option, you can use the actual Bar id as the index (as opposed to some other property like length here) to order the indexed collection.  Change your mapping as shown below to use the id.

Change to <list> element in XML mapping
   1: <list name="bars" inverse="true">
   2:     <key column="foo_id" />
   3:     <index column="id" />
   4:     <one-to-many class="com.intertech.Bar" />
   5: </list>
Change to Foo annotation mapping
   1: @OneToMany
   2: @JoinColumn(name = "foo_id")
   3: @org.hibernate.annotations.IndexColumn(name = "id")
   4: private List<Bar> bars;

The results are better, but still not perfect.  First of all, you may not want your list order dependent on an artificial identifier.  Also, notice the first element is still null.  Why?  Because Hibernate assumes the identifiers will start at 0.  So there is still one place holder for the 0th Bar.  Ughh!!

null
I am a Bar; id = 1 , description:  "this is bar A", and length of:  3
I am a Bar; id = 2 , description:  "this is bar B", and length of:  11
I am a Bar; id = 3 , description:  "this is bar C", and length of:  7
I am a Bar; id = 4 , description:  "this is bar D", and length of:  9

You can use a non-indexed collection like a bag or set.  These non-indexed collections, by definition, don?t maintain order.  Therefore there are no nulls in the collection (see the output results below the mapping changes).

   1: <set name="bars" inverse="true">
   2:     <key column="foo_id" />
   3:     <one-to-many class="com.intertech.Bar" />
   4: </set>

   1: @OneToMany
   2: @JoinColumn(name = "foo_id")
   3: private Set<Bar> bars;

I am a Bar; id = 1 , description:  "this is bar A", and length of:  3
I am a Bar; id = 2 , description:  "this is bar B", and length of:  11
I am a Bar; id = 4 , description:  "this is bar D", and length of:  9
I am a Bar; id = 3 , description:  "this is bar C", and length of:  7

How about using JPA annotations?

But if you still want the collection ordered by a property (column) other than the id, these options are not much of an alternative.  Interestingly, the last option allows you to use standard JPA annotations without special Hibernate annotations to simply retrieve the collection in an ordered fashion and without nulls.  Simply use the @OrderBy annotation to signal to Hibernate (or other JPA implementation) to use an ordered by clause in the SQL to retrieve the associated items (Bars in this case) and drop the Hibernate specific IndexColumn annotation.

   1: @OneToMany
   2: @JoinColumn(name = "foo_id" )
   3: @OrderBy(value="length")

Notice the where clause in the SQL before the results below.

Hibernate: 
    select
        bars0_.foo_id as foo4_0_1_,
        bars0_.id as id1_,
        bars0_.id as id1_0_,
        bars0_.description as descript2_1_0_,
        bars0_.foo_id as foo4_1_0_,
        bars0_.length as length1_0_ 
    from
        Bar bars0_ 
    where
        bars0_.foo_id=? 
    order by
        bars0_.length asc
I am a Bar; id = 1 , description:  "this is bar A", and length of:  3
I am a Bar; id = 3 , description:  "this is bar C", and length of:  7
I am a Bar; id = 4 , description:  "this is bar D", and length of:  9
I am a Bar; id = 2 , description:  "this is bar B", and length of:  11

Collection now ordered and without nulls! And your code is more portable given all annotations are now standard JPA annotations importing javax.persistence vs. org.hibernate annotations).

   1: import java.util.List;
   2:  
   3: import javax.persistence.Entity;
   4: import javax.persistence.GeneratedValue;
   5: import javax.persistence.Id;
   6: import javax.persistence.JoinColumn;
   7: import javax.persistence.OneToMany;
   8: import javax.persistence.OrderBy;
   9:  
  10: @Entity
  11: public class Foo {
  12:   // code removed for brevity
  13: }

Wrap up

To learn more about Hibernate?s collection mapping see the documentation here.  If you are looking for more general help on Hibernate, consider taking Intertech?s Complete Hibernate training or contacting Intertech?s consulting team for project assistance.


Posted by: Jim White
Posted on: 11/27/2011 at 7:32 PM
Tags: , ,
Categories: Java
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Hibernate Lazily Loaded One-To-One Associations

A couple of weeks ago, in my Complete Hibernate class, a student of mine was conducting some of his own experiments with lazy loading at the end of a lab. My class had just learned of Hibernate?s lazy vs. eager loading and the consequences of dangling proxy objects after a session had closed.  He discovered feature in Hibernate that even surprised me.

Hibernate Lazy Loads by Default

By default, Hibernate lazy loads (see here for details), which means when a persistent object is loaded into memory (say with a query or call to get or load) the associated objects are not created. Instead, Hibernate builds a proxy object as a stand-in to represent any associated object. During a session, if an associate object is accessed, Hibernate replaces the proxy with the real object. However, if the session has closed and code tries to access the proxy object (as the real object), an org.hibernate.LazyInitializationException is thrown.

One-to-one Loads Eagerly by Default

My Hibernate student had created a one-to-one relationship between objects and was testing out this default behavior. Surprising (to both of us), when he tried to reach the associated object on a one-to-one mapping (configured with default settings) after closing the session, the object was not a proxy and no exception was thrown!

To better facilitate the understanding of this situation, assume you have two persistent classes: Foo and Bar. Here is the code for both Foo and Bar.

   1: @Entity
   2: public class Foo {
   3:  
   4:     @Id
   5:     @GeneratedValue(strategy = GenerationType.AUTO)
   6:     private Long id;
   7:     @Column(name = "FOO_NAME")
   8:     private String name;
   9:     @Column(name = "FOO_DATA")
  10:     private int data;
  11:  
  12:     @OneToOne(cascade = CascadeType.ALL)
  13:     @JoinColumn(name = "bar_id")
  14:     private Bar bar;
  15:  
  16:     //  ... getters/setters/constructors not shown
  17: }
   1: @Entity
   2: public class Bar {
   3:  
   4:     @Id
   5:     @GeneratedValue(strategy = GenerationType.AUTO)
   6:     private Long id;
   7:     @Column(name = "BAR_INFO")
   8:     private String info;
   9:  
  10:     //  ... getters and setters and constructors not shown
  11: }

Note, via JPA annotations, Foo is associated to Bar in a one-to-one association. However, also note that except for the Cascading Style, no other defaults are overridden in the one-to-one association. So, by default we all assumed Bar to be loaded lazily, which again is the standard Hibernate behavior.

Surprise! When Tom ran his code, using the test case below, the associated Bar instance was getting created and associated to the Foo instance when the Foo instance was obtained. That is, the example code below worked without issue (in particular, note the last two lines of the main method).

   1: public class TestLazy {
   2:  
   3:     public static void main(String[] args) {
   4:  
   5:         Foo foo = new Foo("myfoo", 1234);
   6:         Bar bar = new Bar("some info");
   7:         foo.setBar(bar);
   8:  
   9:         SessionFactory sf = new AnnotationConfiguration().configure()
  10:                 .buildSessionFactory();
  11:         Session session = sf.openSession();
  12:         Transaction trx = session.beginTransaction();
  13:         session.saveOrUpdate(foo);
  14:         trx.commit();
  15:         session.close();
  16:  
  17:         Session session2 = sf.openSession();
  18:         Transaction tx2 = session2.beginTransaction();
  19:         Foo f2 = (Foo) session2.get(Foo.class, 1L);
  20:         // at this point bar on foo instance should be a proxy.
  21:         tx2.commit();
  22:         session2.close();
  23:  
  24:         // if bar property on foo is a proxy, this should cause a
  25:         // LazyInitialization exception.
  26:         Bar b2 = f2.getBar();
  27:         System.out.println(b2);
  28:  
  29:     }
  30: }

Why? Some digging in the Hibernate documentation uncovered a small oddity. It turns out that when in a one-to-one relationship (and when the associated object is optional), it is actually more efficient for Hibernate to just load the associated ?one-to? object as opposed to build a proxy. See here for more details.

How to Get an Associated ?One-to? Proxy

In cases where you actually want a proxy (remember, it might actually be more efficient to just allow the one-to-one associated object to be loaded ? even when not used), make explicit the lazy loading on the one-to-one annotation so that Hibernate builds the proxy as you (and your code) might expect.  Below, the Foo class has been ?fixed? to get Bar to load lazily fashion.

   1: @Entity
   2: public class Foo {
   3:  
   4:     @Id
   5:     @GeneratedValue(strategy = GenerationType.AUTO)
   6:     private Long id;
   7:     @Column(name = "FOO_NAME")
   8:     private String name;
   9:     @Column(name = "FOO_DATA")
  10:     private int data;
  11:  
  12:     //  Add the explicit FetchType
  13:     @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  14:     @JoinColumn(name = "bar_id")
  15:     private Bar bar;
  16:  
  17:     //  ... rest of the code removed
  18: }

Of course, when you run the test code shown above again with this new setting, you?ll get the expected LazyInitializationException.

image

Wrap up

Are you struggling with Hibernate (check out our Complete Hibernate class offering) or other Java open source framework?  Need some help with learning Java technologies or implementing Java EE applications?  Call or email Intertech.  Let our staff of Java experts help you get up to speed faster.


Posted by: Jim White
Posted on: 10/27/2011 at 5:33 PM
Tags: , ,
Categories: Java | Database
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Clarifying Spring Framework IDs and Names

All Spring beans must have an identifier. It says so right in the Spring documentation:  "Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean."

Identifier Confusion

Unfortunately, the fact that a Spring bean can have an "id" and a "name" makes things confusing.  Making matters worse, creating two beans with the same identifier (id or name) doesn't necessarily lead to an exception.  Huh?  Say what?  An example is in order to help clarify.  Assume, as shown below, you have two beans (foo and bar) defined in a Spring beans XML configuration file.

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <beans xmlns="http://www.springframework.org/schema/beans"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   4:     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   5:     <bean id="foo" class="com.intertech.Foo">
   6:     </bean>
   7:     <bean id="bar" class="com.intertech.Bar">
   8:     </bean>
   9: </beans>

Code to get a bean, in this case the foo bean, might look like this sample.

   1: FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(new String[] { "springbeans.xml" });
   2: Foo f = (Foo) context.getBean("foo#");

As you may or may not know, you can use name in place of (or in addition to) id when defining the beans.  Per the Spring 3 documentation, "you use the id and/or name attributes to specify the bean identifier(s)."

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <beans xmlns="http://www.springframework.org/schema/beans"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   4:     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   5:     <bean name="foo" class="com.intertech.Foo">
   6:     </bean>
   7:     <bean name="bar" class="com.intertech.Bar">
   8:     </bean>
   9: </beans>

This doesn't change any of the Java code.  So the question is why?  Why have a name instead of a bean id?  Why have an id and a name?  The reason is that bean ids correlate directly to the XML element id and the XML specification limits the characters that can be used in ids.  Special characters like #, @, $, *, /, and more are not allowed in the id attribute.  If you add one of these special characters to the id, you get an XmlBeanDefinitionStoreException thrown when the configuration is read by the container.  The exception indicates the id "is not a valid value for 'NCName'."

So the name attribute functions just like the id attribute on a bean - uniquely identifying the bean - but it allows the bean unique identifier to contain special characters.  These special characters can be especially helpful in certain types of mapping.  For example, the "/" character can be very useful in identifying certain beans in MVC and RESTful situations.

Only 1 id, but Many names

The name attribute allows for many "aliases."  That is a collection of identifiers that can be used to identify the bean.  Below, for example, the foo bean is also identified by "myFoo", "kingBean", and "notBar" names.  Multiple bean names need only be separated by comma, semi-colon or whitespace.  According to the Spring documentation "A bean will almost always have only one id, but if a bean has more than one id [name], the extra ones can essentially be considered aliases."  So bean names are, if you will, "extra" identifiers.

   1: <bean id="foo" name = "myFoo,kingBean,notBar" class="com.intertech.Foo">
   2: </bean>

Again, the Java code doesn't care which id or name is used.  The following code all results in the container returning a Foo instance in each case.

   1: Foo f1 = (Foo) context.getBean("foo");
   2: Foo f2 = (Foo) context.getBean("kingBean");
   3: Foo f3 = (Foo) context.getBean("notBar");
   4: Foo f4 = (Foo) context.getBean("myFoo");

Names Still Must Uniquely Identify

However, the names must still uniquely identify a bean.  When you try to reuse the name (as shown below, with two beans having the name "kingBean") or when the id of a bean matches the name of another bean, an BeanDefinitionParsingException - Bean name 'kingBean' is already used in this file - is thrown by the container when the configuration is read.

   1: <bean id="foo" name="myFoo,kingBean,notBar" class="com.intertech.Foo">
   2: </bean>
   3: <bean id="bar" name="kingBean" class="com.intertech.Bar">
   4: </bean>

Non-unique Bean Id or Name Across Bean Files (and what to do about it)

Where things get a little interesting is when bean definitions are spread out across many configuration files.  Say, for example, the Foo bean is defined in beans1.xml while the Bar bean is defined in beans2.xml.

beans1.xml

   1: <beans xmlns="http://www.springframework.org/schema/beans"
   2:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   3:     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   4:     <bean id="foo" name="myFoo,kingBean,notBar" class="com.intertech.Foo">
   5:     </bean>
   6: </beans>
beans2.xml
   1: <beans xmlns="http://www.springframework.org/schema/beans"
   2:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   3:     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   4:     <bean id="bar" name="kingBean" class="com.intertech.Bar">
   5:     </bean>
   6: </beans>

Now, if the id or name of either bean (in this case the kingBean name) is non-unique, you surprisingly get no exception thrown by the container!!!

   1: FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
   2:         new String[] { "beans2.xml", "beans1.xml" });
   3: //works fine
   4: Foo f = (Foo) context.getBean("kingBean");

What is the "secret sauce" that makes this work?  Or maybe stated more appropriately - Why doesn't this break?  The documentation says "the last bean definition with the same id [or name] wins, respectively to the order of the xml files.'  In the example Java code above, beans1.xml is loaded by the container after beans2.xml.  Therefore, beans1.xml wins in identifying the bean with the name kingBean.  Had the files been read in reverse order, then kingBean would identify a Bar object.

   1: FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
   2:         new String[] { "beans1.xml", "beans2.xml" });
   3: Bar b = (Bar) context.getBean("kingBean");

If this sounds scary to you, you can turn off this default behavior and make cause bean ids/names to be unique across all configurations of the container.  Look into the DefaultListableBeanFactory for how to the setAllowBeanDefinitionOverriding( ) method.  You should also read this post.

Wrap Up

Hope this helps you better understand Spring bean identification.  If you are interested in learning more about Spring or other Java topic, take a look at Intertech's course curriculum.  Give us a week to improve your skill set. 


Posted by: Jim White
Posted on: 10/25/2011 at 8:07 PM
Tags: , ,
Categories: Java | Spring Framework
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

JavaOne 2011 - Highlights

I returned from JavaOne a week ago.  Overall, again it was a good conference that provided a lot of information on the current state and future direction of Java - that is the Java language, Java platform and Java tools.  I have been to a few conferences this year.  Like it or not, JavaOne is still the conference to get the most complete picture of the state of Java and figure out what has been done in the last year and what is going to happen in next few years with Java.

Is Java Dead?

A few years ago, I wrote an email to a number of my professional friends.  The email was entitled:  "Is Java Dead?"  A few years ago, our training and consulting company saw a rather large decline in Java training class attendance and Java consulting engagements.  I openly asked my friends for their thoughts and feedback at the time.  Was it just economy driven?  Was it a maturity issue with Java - so well entrenched that training and consulting help was no longer needed?   It was at the same time that Oracle had purchased Sun and so I also wondered if the community was starting to have second thoughts about new stewardship of the Java language.  At the time, most of my friends politely suggested, in not so many words, to "give it time."  They were right.  We have seen a resurgence in the number of Java projects and students returning to Java (and other classes) in droves.

Dead... hardly!

The resurgence or return to Java (if there ever really was a loss) was also evident at JavaOne.  Attendance was 2x over last year (Oracle's figure not mine). Certainly much much larger than two years ago where the drop off in attendance was palatable.  I remember sitting in some sessions with less than 10 people.  Not this year where the session rooms were packed to capacity.

Oracle?s commitment to Java, that was once questioned by some, should not be anymore.  Rest easy Java faithful.  I saw no hint that Java was dead, dying or doing anything other than growing under Oracle stewardship.  Having said that, I think Oracle does and will continue to move a little more cautiously (with regard to releases, announcements, partnerships, etc.).  For example, Oracle announced at the conference that Java/JDK 8, which was suppose to be released next summer, is now delayed a couple of summers (coming summer 2013).  In fact, for those that have followed recent developments, Java 8 is really a slice of what was originally to be released with Java 7.  So how late you consider Java 8 is open for debate.  However, the work they (Oracle) have done this year and plan on for the next year is considerable.  Also, one gets the feeling they seem to have a little more of a formal and structured game plan and reasonable schedule for Java products than Sun ever did.

Just the Facts Ma'am

The shape of the conference has changed over the years.  Sun would have probably saved the Java 7 release (which was released with little fanfare in July) for the JavaOne conference.  A few announcements were made (see below), but they weren't the stuff of tech headlines.  It is also evident that Oracle uses the conference to reward big partners and isn?t shy about it.  Gone are the really big announcements in opening day keynotes or the James Gosling presented Java Duke awards that highlighted Java in interesting things.  Many of the keynote speeches were a complete waste of time in my opinion.  They started out as dry marketing pitches from Intel, Juniper Networks and the like.  Eventually you got to the tech and strategy announcements, but these speakers were often pushed on time.  Also gone or rare are the talks by ?normal? developers that give you the real pluses/minuses of a technology like in years past.  There were a few (Adam Bien stands out), but many of the session speakers were Oracle people with an occasional third-party side-kick to echo how wonderful the technology/API/etc. was.

Java 7 and Java EE 6

An audience survey in the last keynote (from the Open JDK community) suggested a vast majority of Java development shops are (or have been) moving quickly to Java EE 6 and Java 7.  For good reasons.  Java EE 6 has a number of very good features that make the platform a competitor to frameworks like Spring, Hibernate, Google Guice, etc.  In some respects, they outshine those now older platforms.  If you haven't tried out Java Enterprise in a while, its time to come back.  Gone are complex EJBs, do it yourself persistence and do it yourself dependency injection.  Java EE 6 is providing a full application framework with some appropriate levels of abstraction.  Annotated POJOs are in Java EE just like you find in Spring or other framework.

Where are the Vendors?

The vendor displays were a bit disappointing at Java One 2011.  Fewer and smaller booths - especially from third parties.  I am not sure of the reasons.  Perhaps space limitations, or because shows are poor investments for companies.  Whatever the reason, I look forward to going to the exhibit floor each year and seeing the latest tools, services, etc. being offered by the community.  I thought the offering this year had much less than years past.  Perhaps with the rise conference attendees this year, we'll see more vendors next year.

Announcements and other Conference Highlights.

So, here are some of the highlights, findings, and thoughts I collected from the week.

On Java SE
  • Java JDK 7 was released at end of July 2011.  It includes:  small literal changes for numeric, diamond operator, switch on strings, multi-exception catch blocks, try with resources (implicit close), better vararg support, new Java FX.
  • Java JDK 7u2 ? to be released before end of the year.
  • JDK 8 ? was to be released summer 2012 and is now Summer 2013  This release will probably include lambda (closures), modules, FX 3.0, JavaScript on JVM, better device support (access camera, GPS, accelerometer, etc.).
  • HTML 5 support ? project Avatar probably in Java 8 (?realistically?) however FX already supports some of HTML 5.
On Java FX 2.0
  • Java FX 2.0 was one if not the highlight of the show.  Long term this will be the Java client side solution ? replacing Swing.
  • They even have migration path guidelines to move from Swing to FX.
Java EE 7
  • To be released around Q3, 2012
  • In general, Java EE 7 will focus on cloud.  That is in being a PAAS (platform-as-a-service).  Interestingly, an "expert panel" on the topic couldn?t really say what that means.  Many claimed ?much of Java EE 6 already supports and does cloud stuff.?  Others on the panel admitted they "weren't really big fans of cloud."
  • What is certain is that it will support multi-tenancy  (in JPA, JMS, etc.).
  • It will also include JSON API and Caching API.
  • It may or may not contain modularity depending on the timing and condition of the feature in Java 8.
CDI - Context and Dependency Injection for Java EE
  • There were some big talks on this new Java EE 6 feature.
  • It is based on Seam2, Guice, Spring.
  • It actually provides more than what Spring has.
Java EE 6 - new patterns emerging?
  • I attended some fantastic talks by Adam Bien (adam-bien.com) on Java EE 6 (cool parts and new patterns).  Some of his comments:
    • Interfaces should be out of EE apps
    • Delegates ? wasteful, don?t need them
    • Don?t worry about stateless/stateful.  Keep your state.  Makes it fast. (only Twitter, Google and really big apps need to worry about stateless)
    • Don?t make everything extensible
    • Configuration over convention is bad.
    • DAOs are superfluous.
    • DRY is the principal of the day (see configuration issue, DAO issue, delegates, etc.)
    • Forget code coverage.  Unit test the hard stuff and don?t worry about the rest.
    • All the old Java EE patterns should go away
    • Key to new Java EE 6 apps:  CDI (glue between components/layers, JPA (persistence), EJB for biz code (provides threads, transactions, etc.), JAX-RS.  This is at heard of Adam?s productive strategy
    • Java EE 6 is bottom up.  J2EE was top down.
  • X-Ray demo application/project from Adam and his books provide insight/details to these strategies
CLDC 7/Java ME - Lot more like regular Java (Even Java 7 features)
  • Java ME is to be a proper subset of SE (even run on SE)
  • Working to converge ME to SE
  • Release at least a year out

A Plea to Oracle for Next Year

Space was constantly an issue. JavaOne is held now at the same time as Oracle Open World (the big Oracle conference). They get Moscone Center in downtown San Francisco and the Java guys get pushed into the Hilton, Parc 55 and Nikki hotels. These are nice hotels, but space is always in limited supply.  The sessions are literally all over these three hotels.  Getting to and from sessions was uncomfortable.  The rooms were usually packet (good for attendance but bad for soaking in the information).  And some of the rooms are really unequipped for presentations - poor acoustics, screens that were too low to see 50% of the screen, poor lighting, hotel music coming on at odd times, etc.  On top of that, I felt like the hotel staffs and security made moving around even worse. Moving from session to session felt like when I was in the Army again being marched from station to station.  Oracle - spend the money and separate the two conferences.  Or, pick a venue that will hold everyone comfortably.

On the plus side, the mobile apps Oracle developed for the conference were wonderful helps.  I had the Android version that allowed me to search for sessions, find my way around, complete session surveys (nice - go green), and generally keep up with the conference.  Way to go on that one Oracle.  Improve it and add to it next year!  By the way, add a better search function that allows me to find a session by date.

Look for new classes at Intertech in 2012

Due to the recent advances in Java SE and Java EE, Intertech is planning updates to much of its Java Curriculum in early 2012.  If we can help you and your organization get up to speed in any Java technology please have a look at our offerings and then contact Dan McCabe.  We would like to see you in class soon.


Posted by: Jim White
Posted on: 10/24/2011 at 8:58 PM
Tags: ,
Categories: Java
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Secrets of the Spring AOP Proxy

By Jim White (Director of Training and instructor)

Spring Aspect Oriented Programming (AOP) is a powerful mechanism to weave cross cutting concerns like security, transactions, exception handling, logging, etc. into business code ("core concerns") without explicitly adding calls to the cross cutting concern.  This allows the cross cutting concern to be updated, removed, swapped out, and generally maintained in a much simpler fashion.

AOP Under the Covers - the Proxy

Having said that, because of the way AOP is implemented, there can seem to be a certain amount of mystery and magic at work.  Your code never invokes the advice methods of an aspect class.  Spring does it for you based on your XML configuration or annotations on the aspect class.  How does the magic happen?  Under the covers, Spring implements a proxy to intercept calls to a target object. 

As an example, say you have a service bean that invokes a call to the saveCustomer( ) method on a DAO.

image

Now say you want to have some logging (a cross cutting concern) occur when a call to any save method occurs on a DAO.  Spring detects your need to call on a logging aspect through your AOP configuration or annotations.  When it does, it builds a proxy (called CustomerDaoProxy for example sake here) around the "target" object - in this case the DAO.

image

Now, on a call to a save method in the DAO, the proxy intercepts the call and routes it appropriately to the appropriate advice method in the aspect class.

image

Issues Given Proxy-based AOP

This proxy-based mechanism allows powerful cross cutting concern code to be isolated from business code.  However, there are all kinds of "gotcha's" that can occur with this type of under-the-covers implementation of which you should be aware.  First of all, aspects cannot advise other aspects.  Per the Spring documentation:

Advising aspects with other aspects?

In Spring AOP, it is not possible to have aspects themselves be the target of advice from other aspects. The @Aspect annotation on a class marks it as an aspect, and hence excludes it from auto-proxying.  (See:  static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-at-aspectj).

This can have some big implications in, sometimes even limitations on, how you implement a cross cutting concern.  Say, for example, your form of logging required adding log statements to a database.  Further, say this database entry required to be performed as part of a transaction (probably a reasonable assumption).  If transactions were implemented through aspects, then you would have the log aspect a target of advice from a transaction aspect.  That's a big "NGH" - not gonna happen.

image

Another such "gotcha" is that local or internal calls to methods within a target object do not cause the advice method to be invoked even with both methods are captured by the AOP pointcut.  In other words, a call from a method in a target to another method in the target does not get intercepted by the proxy.  This results in the advice method never being triggered.  For example, assume you had some sort of business bean that made a call to itself as shown in the simple example below.

   1: @Component("mySubordinate")
   2: public class CoreBusinessSubordinate {
   3:     
   4:     public void doSomethingBig() {
   5:         System.out.println("I did something small");
   6:     }
   7:     
   8:     public void doSomethingSmall(int x){
   9:         System.out.println("I also do something small but with an int");    
  10:     }
  11: }

Also assume you had an aspect constructed and configured with a pointcut capturing both CoreBusinessSubordinate methods as the CrossCuttingConcern class shown here.

   1: @Component
   2: @Aspect
   3: public class CrossCuttingConcern {
   4:     
   5:     @Before("execution(* com.intertech.CoreBusinessSubordinate.*(..))")
   6:     public void doCrossCutStuff(){
   7:         System.out.println("Doing the cross cutting concern now");
   8:     }
   9: }

If another bean was to explicitly call both the target doSomethingBig( ) and doSomethingSmall( ) methods directly, the proxy/interceptor of the aspect would cause the advice to fire twice - as expected.

   1: @Service
   2: public class CoreBusinessKickOff {
   3:     
   4:     @Autowired
   5:     CoreBusinessSubordinate subordinate;
   6:  
   7:     // getter/setters
   8:     
   9:     public void kickOff() {
  10:         System.out.println("I do something big");
  11:         subordinate.doSomethingBig();
  12:         subordinate.doSomethingSmall(4);
  13:     }
  14: }

Results of calling kickOff above given code above.

I do something big
Doing the cross cutting concern now
I did something small
Doing the cross cutting concern now
I also do something small but with an int

However, if instead of calling the doSomethingSmall( ) method from another bean, it was called from inside the target as shown in this next example, the advice fires only one time!

   1: @Component("mySubordinate")
   2: public class CoreBusinessSubordinate {
   3:     
   4:     public void doSomethingBig() {
   5:         System.out.println("I did something small");
   6:         doSomethingSmall(4);
   7:     }
   8:     
   9:     public void doSomethingSmall(int x){
  10:         System.out.println("I also do something small but with an int");    
  11:     }
  12: }
  13:  
  14: --------------------------------------------
  15:  
  16: public void kickOff() {
  17:     System.out.println("I do something big");
  18:     subordinate.doSomethingBig();
  19:     //subordinate.doSomethingSmall(4);
  20: }

New results of calling kickOff above.

I do something big
Doing the cross cutting concern now
I did something small
I also do something small but with an int

The internal call from the target method to another target method escapes the aspect interceptor.

Work Around

You can sometimes find a work around for AOP proxy issues.  For example, you can work around this last issue by exposing the proxy to the target.  When configuring autoproxy development in your configuration, add an expose-proxy attribute and set its value to true (by default it is false).

   1: <aop:aspectj-autoproxy expose-proxy="true"/>

Now in your target code, you can reroute self-invocating methods back through the target proxy.  Use AopContext.currentProxy( ) to get the proxy object and then invoke the internal target method through the proxy as shown below.

   1: public void doSomethingBig() {
   2:     System.out.println("I did something small");
   3:     //doSomethingSmall(4);
   4:     ((CoreBusinessSubordinate) AopContext.currentProxy()).doSomethingSmall(4);
   5: }

Of course, take heed that this tightly couples your core business concern to AOP - something you are trying to avoid with AOP to begin with.  So it may be better to refactor the code such that internal calls are not required when you need advice to fire on all methods.

Wrap Up

I owe a "thanks for the great question" credit to one of my students (Johannes) from my latest Spring  class.  Through some of his experimentation and questions in class, he provided the inspiration for this blog post.  Or as I like to say in class, he won the "stump-the-chump" award this week with yours truly serving as the chump.  If you would like to learn more about Spring please consider taking Intertech's Complete Spring Framework 3 class (see here).  Please contact Dan McCabe for further details.


Posted by: Jim White
Posted on: 8/29/2011 at 5:47 PM
Tags: , , ,
Categories: Java | Spring Framework
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Android and iOS Rule Smartphone Markets

In their recently released 2011 second quarter (Q2-2011) report on smartphones, Gartner indicates that almost two thirds of smartphones sold across the globe are now either Android or iOS devices (see here).

Here are some of the reported findings:

  • iOS and Android devices now account for 62% of the world's and 84% of North American smartphone sales.
  • This percentage almost doubles numbers from last year (was 32%).
  • Android devices now account for 43.4% of smartphones sold globally (as of 1st quarter last year it was less than 10%).
  • iOS has 18.2% of smartphone sales around the world (up from 14.1% in the 1st quarter of last year).
  • Globally, Symbian (Nokia) is still in second place (22%) but falling rapidly (down from 41% 1st quarter last year).
  • Research in Motion (RIM) was 18.7% last year and now holds only 11.7% of global sales.
  • Microsoft - "still having trouble getting traction" - slipping to 1.6% from 4.9% of global sales.

If you or your company is looking to crack into the application space of the two leading smartphone platforms, consider taking Complete Android or Complete iPhone training classes from Intertech.  Contact Dan McCabe (dmccabe@intertech.com) for more details.


Posted by: Jim White
Posted on: 8/12/2011 at 5:37 PM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Android Widget Size

When teaching Android, I find students confused by the many "size" or dimensional properties on Android TextView and various descendent widgets like Button, CheckBox, EditText, etc.  Often, the size of any widget can be dictated by its layout, content or other aspect.  But you can directly set the size by property.  Unfortunately, there a number of properties that determine the size of these widgets.

Units of Measure

What might add to the confusion is that the dimensions (height and width for example) can be specified in one of many different units of measure in the layout resource file.  Specifically, the height and width can be specified in pixels, density-independent pixels, scaled-independent pixels, inches, millimeters or em.  Inches and millimeters are probably straight forward enough.  However, the fact that there are three types of pixel definitions leads to questions about the differences among the other options.

Density-independent pixel

The pixel unit of measure refers to the actual number pixels on the screen.  Because the size and number of pixels can vary greatly across devices, widget height and width can vary when using pixels to determine the widget size.  A density-independent pixel is an abstract unit of measure.  It is based on a screen with a density of 160 pixels (or dots) per inch (dpi).  The formula is physical pixel = density-independent pixel * (160/ system dpi).  So, if you had a device with 320 pixels (dots) per inch, 1 density-independent pixel would equal 2 physical pixels.

Scaled-independent pixel

Scaled-independent pixel is like the density-independent pixel unit of measure.  However, scaled-independent pixels are also scaled by the user's font size preference. When using a widget (like EditText or TextView) that displays text, an adjustment may be made for the text as part of the widget display.  At the default font size settings, 1 scaled-independent pixel = 1 density-independent pixel.  However, this can change if the user sets the font size to be larger or smaller.

Developers are actually encourage to use the density-independent (or scaled-independent) unit of measure when defining widgets because it allows the widgets in an applications to preserve the appearance of physical size across many different sized devices.  In other words,  your widgets are automatically scaled on screens with different densities so that the look/feel of the user interface is preserved. 

For more information regarding the various pixel units of measure, see here.

EM

An em is a unit of measure derived in the field of typography (the art and technique of arranging type).  Originally, the unit was derived from the width of the capital letter 'M' (thus the name - and the way you pronounce this unit of measure).  What an em defines is the proportion of a given letter's width and height with respect to the point size.  The em should be the same for all fonts at a specified point size - providing a font/typeface independent unit of measure.  For example, in a 16 point typeface, 1 em = 16 points.  See here for more information on the em unit of measure.

Unit of Measure Abbreviations

When specifying a size in inches, millimeters, pixels, density-independent pixels, or scaled-independent pixels (all but EM), abbreviations are used.  The table below provides the abbreviation and an example dimension setting.

Unit of Measure Abbreviation Example
inches in "0.5in"
millimeters mm "20mm"
pixels px "100px"
density-independent pixels dp or dip "100dp" or "100dip"
scaled-independent pixels sp "100sp"

Physical Height/Width Properties

With an understanding of the units of measure, a better look at the widget size can be accomplished.  There are indeed several properties which control the physical dimensions of TextView (and all subclass) widgets.  These include the following properties:

  • height/width
  • maxHeight/minHeight
  • maxWidth/minWidth
  • ems
  • minEms/maxEms
  • textSize

Height/Width

The first two properties, height and width, set the specific height and width of the associated view.  In the example below, both the height and width are set to 100 pixels.  [Note:  programmatically, setHeight(int) and setWidth(int) sets these widget properties.  However, these methods only work in the pixel unit of measure.]

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:         android:layout_width="wrap_content" android:layout_height="wrap_content" android:height="100px" android:width="100px"></Button>

image

Layout Affect

Remember, when using layout ViewGroup (like LinearLayout), the layout often dictates the height and/or width of a widget.  In the example below, the height and width are set to 100 pixels, but the layout_width and layout_height are set to fill_parent.  This has an overriding effect and causes the button to be displayed with nothing close to the 100x100 pixel sizes.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="fill_parent" android:layout_height="fill_parent"
   3:     android:height="100px" android:width="100px"></Button>

image

Max and Mins

The height and width properties call for the widget to be a specific size (when not affected by layout management).  The maxHeight/MinHeight and maxWidth/MinWidth can be used instead of the height/width properties.  Min and max properties inform Android what the maximum (at most) and minimum (at least) sizes can be for a widget.  Some layouts and the presence/non-presence of contained text can impact the dimensions of a widget.  These properties help to ensure the minimum and maximum width/height.

Unless the height and/or width are set between their respective min/max values, you don't want to use the height or width property with min/max properties.  In fact, you will find that the min/max properties override the height/width properties.  In the example below, note the minHeight/maxHeight properties are set to 100 and 200 pixels respectively.  When the height is set to 10px, it has no effect.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:minHeight="100px" android:maxHeight="200px" android:height="10px"></Button>

image

If the height property is set to a value between min/max, then it dictates the size of the widget.  Here, the height is set to 150, between the min and max values of 100 and 200 pixels.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:minHeight="100px" android:maxHeight="200px" android:height="150px"></Button>

image

TextSize

Widgets, like the push button, often have associated text.  The textSize property can and often does affect the size of not only the text displayed but also the associated widget.  Notice what happens to the button when the size of text is set to 100 pixels.  The corresponding button grows to meet the text demands.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:textSize="100px"></Button>

image

However, when the height and width are set (either directly or with min/max properties), the textSize setting is overridden.  In the example below, the textSize is still set to 100 pixels, but the height is set to 10 pixels.  You can't even read the text anymore because the height of the resulting button is too small to display it.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:textSize="100px" android:height="10px"></Button>

image

Using EMS

Special properties (and setters/getters from a programmatic perspective) are used to provide an EM dimension.  Below are two images, one with the ems value set to 10 and the other set to 20.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:ems="20"></Button>

image

image

 

Don't use the height/width with ems values.   The height/width will override the ems values.

   1: <Button android:text="Push me now" android:id="@+id/button1"
   2:     android:layout_width="wrap_content" android:layout_height="wrap_content"
   3:     android:ems="20" android:height="100px" android:width="100px"></Button>

image

Wrap up

With all these "dimensional" properties and the ways they can be impacted by the layout, content, unit of measure, etc. its no wonder people can be a little confused on how to set the dimensions of an Android TextView (or descendent) widget.  Hopefully this post can help you figure out what works best for your mobile application need.  If you are looking for more help on developing Android  applications, consider taking Intertech's Complete Android training (see here for more details and contact Dan McCabe at dmccabe@intertech.com to reserve a seat).


Posted by: Jim White
Posted on: 7/17/2011 at 9:08 PM
Tags: , ,
Categories: Android | Mobile
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Subscribe to this BlogRSS comment feed

Android Layout and ID Attribute

By Jim White (Director of Training and Instructor)

In Android, there are two ways to construct Activities (Activities make up the bulk of the graphical user interface associated with Android applications).  You can programmatically add View and ViewGroup components (i.e. "widgets") to the Activity in Java program code.  However, the programmatic approach is typically reserved for more dynamic and/or complicated UI scenarios.  The alternate (and typical) way to construct an Activity is to use XML layout files.

When building the layout file, many people learning Android are often confused by the android:id attribute used in the definition of many components.  In this post, I attempt to clarify the what's and why's of the ID attribute.

Why an ID?

When defining your layout in XML, you may first be surprised to learn that the android:id is optional!  You only need to add an android:id attribute to any View component in the layout file when you want to reference the associated component.  That is, you want to reference the component in your Java code or when defining layout in XML.

Using the android:id Reference in Java Code

Sometimes, you define your Activity user interface in XML (through layout files), but then use Java code to make changes to the Android components.  For example, in the layout shown below an Activity's layout includes an EditText widget.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   3:     android:orientation="vertical" android:layout_width="fill_parent"
   4:     android:layout_height="fill_parent">
   5:     <EditText android:text="Hi there" android:id="@+id/GreetingText"
   6:         android:layout_width="wrap_content" android:layout_height="wrap_content"></EditText>
   7:     <Button android:text="Push Me" android:id="@+id/HelloButton"
   8:         android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="buttonPushed"></Button>
   9: </LinearLayout>

image

For example sake, say you wanted to change the text in the EditText widget when the user clicks the "Push Me" button.  The Java code to accomplish this work first needs to get a reference to the EditText instance displayed on the user interface.  In order to get a reference to the EditText instance (using the Activity's method findViewById()), you need the EditText to be defined with an android:id.  In this example, the id of the EditText view is GreetingText as defined by the attribute:  android:id="@+id/GreetingText".

Now Java code in the Activity can get a reference to the view and update its text when the the button is pushed (as exemplified below).

   1: public void buttonPushed(View v) {
   2:     EditText greetingText = (EditText) findViewById(R.id.GreetingText);
   3:     greetingText.setText("Hello yourself");
   4: }

Using the android:id Reference In Layout XML

Once a view is defined in XML, the view can also be referenced by other view components in a layout file via the android:id.  For example, what if the LinearLayout above were instead made a RelativeLayout.  In a RelativeLayout, views can be positioned on the screen relative to the position of another view or the parent view.  However, in order to indicate where a view should be placed in reference to another view, the android:id is needed to provide reference.  In the example below, the Push Me button is placed to the right of the EditText view.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   3:     android:layout_width="fill_parent" android:layout_height="wrap_content">
   4:     <EditText android:text="Hi there" android:id="@+id/GreetingText"
   5:         android:layout_width="wrap_content" android:layout_height="wrap_content"></EditText>
   6:     <Button android:text="Push Me" android:id="@+id/HelloButton"
   7:         android:layout_width="wrap_content" android:layout_height="wrap_content"
   8:         android:onClick="buttonPushed" android:layout_toRightOf="@id/GreetingText"></Button>
   9: </RelativeLayout>

Notice that the Push Me button, uses the EditText android:id to reference the view in order to position itself to the right of the EditText view (android:layout_toRightOf="@id/GreetingText").

image

Why the @+

Ok, so now you know why and how android:id's are used.  The next question is usually about the special symbols used in defining and referencing the android:id.  "What's with the @+ and @ in front of the android:id attribute when defining or referencing a view like EditText above?"

Use @+ on the first occurrence of a given android:id in a layout (XML) file.  It might be in the definition of the view or it might be in a reference - which ever is first.  In the example above, the EditText view is defined before the Button.  So the @+ is used on the android:id attribute in EditText.  However, if the Button was defined first, the @+ would be used on the relative layout positioning in the Button (as shown below.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   3:     android:layout_width="fill_parent" android:layout_height="wrap_content">
   4:     <Button android:text="Push Me" android:id="@+id/HelloButton"
   5:         android:layout_width="wrap_content" android:layout_height="wrap_content"
   6:         android:onClick="buttonPushed" android:layout_toRightOf="@+id/GreetingText"></Button>
   7:     <EditText android:text="Hi there" android:id="@id/GreetingText"
   8:         android:layout_width="wrap_content" android:layout_height="wrap_content"></EditText>
   9: </RelativeLayout>

The plus sign (+) indicates to the Android SDK's aapt tool (which is automatically invoked through Eclipse) that this is a new resource name.  Therefore, the aapt knows that it must add the reference (in this case GreetingText) to the generated R.java file.  Below, you can see the GreetingText id added to the R.java file for this simple demonstration project.

   1: /* AUTO-GENERATED FILE.  DO NOT MODIFY.
   2:  *
   3:  * This class was automatically generated by the
   4:  * aapt tool from the resource data it found.  It
   5:  * should not be modified by hand.
   6:  */
   7:  
   8: package com.intertech;
   9:  
  10: public final class R {
  11:     public static final class attr {
  12:     }
  13:     public static final class drawable {
  14:         public static final int icon=0x7f020000;
  15:     }
  16:     public static final class id {
  17:         public static final int GreetingText=0x7f050001;
  18:         public static final int HelloButton=0x7f050000;
  19:     }
  20:     public static final class layout {
  21:         public static final int main=0x7f030000;
  22:     }
  23:     public static final class string {
  24:         public static final int app_name=0x7f040001;
  25:         public static final int hello=0x7f040000;
  26:     }
  27: }

Subsequent references to the id can drop the "+" and just use the android package namespace (as in the case of the original Push Me button for relative positioning in the example above).

Some Special android:ids

Note that there are some special built-in android:ids.  The android:id for a ListView of a ListActivity is one such example.  That is, if your Activity is a subclass of ListActivity, you don't usually need a layout (the main view is just the list shown in the ListActivity).  However, if you want to customize the underlying layout and/or ListView, you  need to identify the associated ListView with @android:id/list so the ListActivity knows which view is the main list for the activity.

As another example, a tabbed view often requires components identified by android:id/tabhost, android:id/tabs and android:id/tabcontent.

Wrap Up

For more information about the definition and use of ids in Android layouts and code, see developer.android.com/guide/topics/resources/layout-resource.html#idvalue.  If you are looking for more help on developing Android  applications, consider taking Intertech's Complete Android training (see here for more details and contact Dan McCabe at dmccabe@intertech.com to reserve a seat).  Or, if you need mobile application consulting help, contact Ryan McCabe at rmccabe@intertech.com to get started.


Posted by: Jim White
Posted on: 7/5/2011 at 3:21 PM
Tags: , ,
Categories: Android | Mobile
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed
Contact Us 651-994-8558 1-800-866-9884
Home | Training | Curriculum | Course Finder | Schedule | Enroll | Twin Cities Java User Group | Consulting | Foundation | Jobs | About Us | Our Story | Press Room | Instructors | President | Map & Directions | Sitemap

Java Training | JSF / Struts / Spring / Hibernate Training | Java Power Tools Training | .NET 4.0 & Visual Studio 2010 Training | .NET 3.5 and Visual Studio 2008 Training | .NET 2.0 and Visual Studio 2003 Training | Prism / MVVM / MEF Training | Microsoft Web Development Training | Cloud Computing Training | Ajax / Web Services / XML Training | Groovy and Grails Training | SQL Server 2008 Training | SQL Server 2005 Training | Mobile Development Training | SharePoint 2010 Training | SharePoint 2007 Training | Agile, Process, Analysis & Design Training | Arch/Design Patterns Training | Microsoft Official Curriculum Training | Web Development Training | Ruby Training | Rational Application Developer (RAD) Training | WebSphere Application Server Training | WebSphere Portal Training | WebLogic Training | Boot Camp Training | Project Management Training | C++ Training | Metro / WinRT / Windows 8 Development Training | Retired

Intertech delivers training on-site and virtually serving cities including Phoenix, AZ | San Francisco, CA | Los Angeles, CA | San Diego, CA | San Jose, CA | Washington, DC | Chicago, IL | Orlando, FL | Boston, MA | Duluth, MN | Minneapolis St. Paul, MN | Rochester, MN | Raleigh-Durham, NC | New York, NY | Philadelphia, PA | Austin, TX | Dallas, TX | Houston, TX | Seattle, WA.