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

Intertech Struts Training Video | 5 min Intro

Learn more about struts by watching this 5min video...


Posted by: Intertech
Posted on: 9/8/2011 at 3:37 PM
Tags: ,
Categories: Java | Web Development
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Subscribe to this BlogRSS comment feed

Express JUnit Training Video

Jim White introduces Express JUnit


Posted by: Intertech
Posted on: 9/1/2011 at 4:10 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

Java Training Video | Free Java Intro


Posted by: Intertech
Posted on: 8/9/2011 at 3:44 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

Processing XML Files with Groovy: Creating

Intro

Do you write code that reads and/or writes XML files or in-memory structures?  XML files are a useful data exchange for programs, but are not usually fun to hand-edit code for in most languages.

If you haven't seen how easily Groovy handles XML data, read on...  It can simplify the coding such that you will probably want to use Groovy for this next time!  It can be particularly useful with test data.

This post covers an intro how to on creating XML with Groovy.  I plan to cover an intro how to on parsing XML with Groovy in the future.

For the examples, while much Groovy convention is to chain method calls, I deliberately separated object definitions and method calls into more simple statements to help understand the separate pieces as an introduction.  Additionally, the examples were written with Groovy 1.8.0.

Creating XML

Groovy primarily has the MarkupBuilder and StreamingMarkupBuilder classes that do the XML creation dirty work (along with their helper classes).  These examples only focus on the StreamingMarkupBuilder as it also has namespace support and handles large documents with less memory usage.  However, using the others is very similar.

The "writeFile" Method for All Examples

Before jumping into the XML creation examples, we need to cover a common method used by each example: "writeFile".  I extracted the common code from each example to it to simplify the example, and show the near-template code for setup and use.

   1: def writeFile(fileName, closure) {
   2:     def xmlFile = new File(fileName)
   3:     def writer = xmlFile.newWriter()
   4:  
   5:     def builder = new StreamingMarkupBuilder()
   6:     def Writable writable = builder.bind closure
   7:     writable.writeTo(writer)
   8: }

The writeFile method requires two parameters (line 1):

  • The first parameter is the full path of the file name to create.
  • The second parameter is the closure passed to the StreamingMarkupBuilder's bind method.

Using the StreamingMarkupBuilder class:

  • The bind method requires a closure and returns a Writable instance (line 6).  The closure contains the code for generating the XML.  The bind method will invoke the closure to generate the XML.
  • Use the Writable (line 7) to output the XML from the closure to the desired destination, whether a file or a String (review the doc or use autocomplete in your favorite IDE to learn the other uses of Writable).

The following examples will explain creating the closure for writing. the XML.  They start with a simple example and each adds one new "feature" to help keep this "how to" clearer.  The last example shows dynamically generating the XML from a map of data versus statically defined in the closure.

Example 1: Simple

Example 1 shows creating a simple XML file from static elements defined in the closure.

   1: def createFromStatic_Simple() {
   2:     def xmlClosure = {
   3:         docroot {
   4:             element(1)
   5:             element('b')
   6:             element('c' + 'c')
   7:             element(2 + 2)
   8:         }
   9:     }
  10:  
  11:     writeFile('/createFromStaticSimple.xml', xmlClosure)
  12: }

 

Example 1 creates the following XMLfile (note: it's created all on one line without formatting; it is formatted it here for readability):

   1: <docroot>
   2:   <element>1</element>
   3:   <element>b</element>
   4:   <element>cc</element>
   5:   <element>4</element>
   6: </docroot>

Comparing the closure defined starting on line 2 of the code example with the created XML file, notice the direct use of the closure structure names and evaluated expressions in the XML file.

  1. Literal names in the closure structure become the element names in the XML file.
    • "docroot" and "element" become element names.
  2. Expressions inside the parenthesis are evaluated and used as the element's value.
    • 'c' + 'c' on code line 6 becomes "cc" on XML line 4.
    • "2 + 2" on code line 7 becomes 4 on XML line 5.
  3. Elements inside the curly braces become the next nested level inside the named element (they are each closures - anonymous closures as they are not bound to variables - and are evaluated at runtime).  The "element"s on code lines 4-6 become <element> entries on XML lines 2-5.

Note: It's important to place the subsequent element definitions on their own line, otherwise, Groovy will dynamically interpret it differently, usually as a map!

Example 2: Nested Elements

Example 2 also shows creating an XML file from static elements defined in the closure, and adds a second nested level of closure elements named "inner".

   1: def createFromStatic_Nested() {
   2:     def xmlClosure = {
   3:         docroot {
   4:             element {
   5:                 inner(1)
   6:             }
   7:             element {
   8:                 inner('b')
   9:             }
  10:             element {
  11:                 inner('c' + 'c')
  12:             }
  13:             element {
  14:                 inner(2 + 2)
  15:             }
  16:         }
  17:     }
  18:  
  19:     writeFile('/createFromStaticNested.xml', xmlClosure)
  20: }
 

Example 2 creates the following XMLfile (note: it's created all on one line without formatting; it is formatted it here for readability):

   1: <docroot>
   2:   <element>
   3:     <inner>1</inner>
   4:   </element>
   5:   <element>
   6:     <inner>b</inner>
   7:   </element>
   8:   <element>
   9:     <inner>cc</inner>
  10:   </element>
  11:   <element>
  12:     <inner>4</inner>
  13:   </element>
  14: </docroot>

Once again, notice the direct use of the element names in the XML file, this time with the addition of another nested element level named "inner".  The same value expressions are moved from the "element" element to the new "inner" element, still within parenthesis.

As the code example shows, to add a nested element, just create a nested closure.

Example 3: Attributes

Example 3 also shows creating an XML file from static elements defined in the closure with nested elements, and adds attributes.

   1: def createFromStatic_NestedAndAttributes() {
   2:     def xmlClosure = {
   3:         docroot {
   4:             element(attr1:1, attr2:2) {
   5:                 inner(attr3:1, 1)
   6:             }
   7:             element(attr1:4, attr2:5) {
   8:                 inner(attr3:'b', 'b')
   9:             }
  10:             element(attr1:7, attr2:8) {
  11:                 inner(attr3:'c' + 'c', 'c' + 'c')
  12:             }
  13:             element(attr1:10, attr2:11) {
  14:                 inner(attr3:2 + 2, 2 + 2)
  15:             }
  16:         }
  17:     }
  18:  
  19:     writeFile('/createFromStaticNestedAndAttr.xml', xmlClosure)
  20: }

Example 3 creates the following XMLfile (note: it's created all on one line without formatting; it is formatted it here for readability):

   1: <docroot>
   2:   <element attr1='1' attr2='2'>
   3:     <inner attr3='1'>1</inner>
   4:   </element>
   5:   <element attr1='4' attr2='5'>
   6:     <inner attr3='b'>b</inner>
   7:   </element>
   8:   <element attr1='7' attr2='8'>
   9:     <inner attr3='cc'>cc</inner>
  10:   </element>
  11:   <element attr1='10' attr2='11'>
  12:     <inner attr3='4'>4</inner>
  13:   </element>
  14: </docroot>

The only difference between examples 2 and 3 is 3 adds element attributes.  To add attributes to an element:

  1. Specify the attributes inside parenthesis, comma separated, followed by an optional value expression as seen in examples 1 and 2.
  2. Specify an attribute with its name, a colon, and its value-expression.

Example 4: Dynamic Creation

Example 4 shows creating an XML file from a map of data using for-each loops in the closure.

   1: def createFromDynamic() {
   2:     def mfgs = [
   3:             'Boeing':['747', '737', '727'],
   4:             'Airbus':['A330', 'A350', 'A380'],
   5:             'Lockheed':['L100', 'L1011', 'C130'],
   6:             'Ilyushin':['IL-62', 'IL-76', 'IL-86'],
   7:             'Fokker':['F28', '50/60', '70/100']]
   8:  
   9:     def closure = {
  10:         manufacturers {
  11:             mfgs.each { key, value ->
  12:                 manufacturer(name:key) { value.each { model (it) }}
  13:             }
  14:         }
  15:     }
  16:  
  17:     writeFile('/createFromDynamic.xml', closure)
  18: }

Example 4 creates the following XMLfile (note: it's created all on one line without formatting; it is formatted it here for readability):

   1: <manufacturers>
   2:   <manufacturer name='Boeing'>
   3:     <model>747</model>
   4:     <model>737</model>
   5:     <model>727</model>
   6:   </manufacturer>
   7:   <manufacturer name='Airbus'>
   8:     <model>A330</model>
   9:     <model>A350</model>
  10:     <model>A380</model>
  11:   </manufacturer>
  12:   <manufacturer name='Lockheed'>
  13:     <model>L100</model>
  14:     <model>L1011</model>
  15:     <model>C130</model>
  16:   </manufacturer>
  17:   <manufacturer name='Ilyushin'>
  18:     <model>IL-62</model>
  19:     <model>IL-76</model>
  20:     <model>IL-86</model>
  21:   </manufacturer>
  22:   <manufacturer name='Fokker'>
  23:     <model>F28</model>
  24:     <model>50/60</model>
  25:     <model>70/100</model>
  26:   </manufacturer>
  27: </manufacturers>

The XML file structure is still defined in the closure (the element and attribute names, and their relationships), but the data is now pulled from a map.  This example shows a typical use - the map (or a list) could have been retrieved from a database or other source.

Conclusion

The examples begin to show easy ways to programmatically create XML files with Groovy.  While these simple examples should get you started, the potential processing is only limited by the closure logic.  Additionally, StreamingMarkupBuilder (and other builders) has some advanced features often accessed through "mkp", which is a special namespace used to access helper markup methods.

Resources


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

New Changes to Oracle's Java Certification Paths

One of the major changes that has happened in the Java world, since Oracle's acquisition of Sun, is in regard to the official certification program.  Following Oracle's certificate taxonomies, Java now has four levels: Associate, Professional, Master, and Expert

The main differences between these categories are:

  • The Associate level establishes competency in basic skills which are considered prerequisite knowledge.
  • The Professional level verifies the holder possesses the expected skill set to be able to effectively develop and use the specified technologies.
  • The Master level is considered the highest level of skills for a specific technology path.
  • The Expert level is used to show expertise in a specific technology that isn't covered in the Associate -> Master certification paths.

The two most popular certifications (Java Programmer and Web Component Developer) fall into the "Professional" category.  A complete list can be found at: the Oracle Middleware Certification page. 

One of the biggest controversies, and sources of confusion, is in regard to a new training requirement.  Beginning October 1st, 2011, anyone who wants to complete the Oracle Certified Master, Java SE Developer and/or the Oracle Certified Master, Java EE 5 Enterprise Architect will be required to complete one training course.  To be clear, the most commonly completed certification programs - Oracle Certified Professional, Java Programmer and Oracle Certified Professional, Java EE 5 Web Component DeveloperDO NOT currently include this training requirement.

I recently communicated with Oracle to receive some clarification on the new rules and changes (my sincere gratitude to Oracle for taking the time to answer these questions):

1) There has been a great deal of confusion regarding the new course attendance requirements for the Java Architect and Java Developer certifications. Could you clarify the requirement (i.e. which specific certifications are affected by this rule - is it just the Oracle Certified Master, Java SE 6 Developer & Oracle Certified Master, Java EE 5 Enterprise Architect? Will any Professional or Expert level courses have the same requirement?)

"ONE course is required. Candidates can choose from one of the courses in each list on http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=449. The certifications that will require training on October 1 are:

Oracle Certified Professional, Oracle Solaris 10 System Administrator
Oracle Certified Expert, Oracle Solaris 10 Security Administrator
Oracle Certified Master, Java SE 6 Developer
Oracle Certified Master, Java EE 5 Enterprise Architect"

2) If someone has completed a portion of the Developer or Architect certification (such as the assignment), prior to October 1st, and finishes up the latter portion after October 1st, will they be exempt from the course attendance requirement?

"The certification path must be completed by October 1, 2011. If candidates submit Assignment and Essay on September 30, it can take up to 4 weeks to grade. If they pass, they are exempt from the training requirement. If they fail, they are required to complete training and resubmit the assignment. We recommend that candidates submit the assignment and complete the essay by August 27 to allow time for grading and also time to resubmit in the event that they fail."

 

3) Other than the piece of paper, what does Oracle see as a benefit? Do certificate holders get first peek at new releases or have preference for attending / presenting at JavaOne?

"Employers look for ways to distinguish employees and prospective employees who have the solid foundation of skills needed for effective performance. The Oracle Certification Program helps the IT industry make these distinctions by establishing a standard of competence in specific job roles.
See below how thousands of members have testified to the value of the Oracle Certification Program*.

97% said they have benefited from certification.
96% would recommend the program to a professional colleague.
89% said they gained more confidence in their Oracle expertise after becoming certified.
Candidates can also view our salary survey http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=305 (tho this survey does not include Java certification)
There is also a 'Certification Lounge' at shows such as Oracle OpenWorld and JavaOne."

 

4) If you take an approved class and don't pass the exam, are you allowed to retake the class for free? What guarantees/limits/warrantees come with the class?

"We would not expect a course to be a complete preparation for an exam. Oracle recommends a combination of training and experience and we encourage candidates to use multiple resources to help prepare for exams. In the recommended training section of each exam page, we provide the course or courses that will best help a candidate prepare for the exam, but the exam will not map back to this course question for question because the course cannot fully address the hands-on practice/experience component of a candidate's preparation strategy.  Oracle University courses come with a 100% satisfaction guarantee http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=94, but this guarantee is not tied to how closely the course maps to the certification exam or to a candidate's exam result.."

 

Additional information on the new Java Certification rules can be found at: http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=449


Posted by: Jason Shapiro
Posted on: 7/27/2011 at 9:27 AM
Categories: Java
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.