Recant: Scalable.DEFINITION != Elastic.DEFINITION

In my earlier post, That’s Right Oracle…, I stated that

What we used to call scalable is now called “elastic”

Ok, so it turns out that’s not exactly true.   Scalable and elastic should always go hand in hand when describing the properties of a Cloud architecture, but the term elastic emphasizes a more efficient tempering of the scale.

Gartner gives an excellent summary:

Scalable and Elastic: The service can scale capacity up or down as the consumer demands at the speed of full automation (which may be seconds for some services and hours for others). Elasticity is a trait of shared pools of resources. Scalability is a feature of the underlying infrastructure and software platforms. Elasticity is associated with not only scale but also an economic model that enables scaling in both directions in an automated fashion. This means that services scale on demand to add or remove resources as needed.

However!!!  You buzzword-dropping execs are not off the hook here!  You’re not impressing anyone!  ;-)  Consider speaking with you’re own words once and a while.  I know that creating a buzz is good for business.  You can make something out of nothing with a powerful enough word.  

 

Java 7 (2011) and Java 8 (2012)- “Let’s get the platform moving again.”

Lest there be any doubt of Oracle’s commitment to the Java SE core, Mark Reinholt shared the previously TOP-SECRET projections for future Java SE releases. He shared his wishlist of core language enhancements which I’m quite sure some other blogger (most likely a JE…Java Expert) will cover ad nauseum (thank you, by the way, whomever you are, that will be awesome).  I look forward to be as confused about Lambda’s as I was about Generics.

The reason I am excited, is that I don’t want to believe that Java is becoming a legacy platform…like my first two platforms did (COBOL and Powerbuilder).   I’m sensing a willingness from Oracle to take some bold moves to bring Java into the 21st century of coding innovation.

Bravo!

Javaone – A few complaints

Don’t get me wrong, friends.   This RAJP is having fun, but I have 4 other Javaones with which to prepare.  [a hint of smugness crosses his face for having not ending his sentence with a preposition...oh so smug]. 

  1. Where’s the steady stream of junk food between sessions?  I couldn’t even find coffee most of the day.  NO COFFEE?  Really guys?  You couldn’t use just a little more of my tuition for coffee?  Even the place that rotates my tires has free coffee!
  2. Keynotes.  First off, as a Javaone attendee, I was not permitted to attend the Sunday night opening keynote.  Just not enough space?  Second, when I finally did get a keynote, it was suits talking business alignments and strategy.  Where are the t-shirt launchers?  Where are the weird little side shows and goofy scripted demos?  Where’s the innovation?  WHERE’S THE GEEK POWER THAT USED TO RUN THIS SHOW?  Why do these Oracle guys think we’d be interested in a bunch of boardroom buzzwords.  They can kiss my “Elastic Cloud”!!
  3. Facility.  Loudest dang meeting room doors in a conference EVER.  
    [he catches a whiff of something...something right....something he needs....it's coffee...not just tables full of emtpy mugs...but actual coffee.]
  4. MMMMMMMm…..coffee and banana nut bread!  So yummy….now, what was I saying?  This is some good stuff.  Moist.  Not too many nuts.    Woot.

That’s right Oracle, keep us far away from Ellison and keep us sedated!

So, Oracle’s strategy for keeping peace at the conference is internment and booze.   I was one of the many javaone attendees who was intercepted trying to attend the opening keynote speech by Larry Ellison.  If you managed to get past the security guard (yes!  effing SECURITY guard) at the escalator, then you were probably identified by sight from about 20 yards by a conference staffer (or perhaps their’s an RFID chip in our badges) and then told, “We’ve had a change of plan.  Javaone has something fun for you at the Hilton.”  To which I responded, “Great!  That DOES sound fun, but we want to hear what Ellison has to say.”  Denied. 

Turns out, we were able to catch part of his talk via simulcast at the Hilton.  Let me break it down for you:

What we used to call scalable is now called “elastic”, and management types LOVE to play with the word “cloud”.  Even better:  Elastic Cloud.

Ok, so “internment” is a bit of a stretch.  We had a good time with good food and plenty to drink, and occasionally, we even looked up at the enormous screens and caught a snippet of what Ellison had to say.  He talked.  And talked. And talked and used a nifty powerpoint presentation with lots of bullet points.

Handy dandy Netbeans feature: Print to HTML

In blogging, I often like to share some code.  Often times, I’ll just take a screen print, crop it, and upload it.   But yesterday I found another way to put formatted code in my posts using Netbeans:  Print to HTML.  It’s under the File menu.

  1. Open your source in Netbeans
  2. Click Print to HTML under the File menu
  3. Choose between “Print to File” and “Print to Clipboard
    
  4. Click the HTML tab (assuming you’re using WordPress
  5. Paste in markup into your blog editor…et voila!


1
/*

 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5
 6 package sample.transfer;
 7
 8 import java.math.BigDecimal;
 9
10 /**
11  *
12  * @author david ctr wilson-bur
13  */
14 public class ProductTO {
15     private Integer productId;
16     private String description;
17     private BigDecimal purchaseCost;
18
19     public String getDescription() {
20         return description;
21     }
22
23     public void setDescription(String description) {
24         this.description = description;
25     }
26
27     public String getManufacturerName() {
28         return manufacturerName;
29     }
30
31     public void setManufacturerName(String manufacturerName) {
32         this.manufacturerName = manufacturerName;
33     }
34
35     public Integer getProductId() {
36         return productId;
37     }
38
39     public void setProductId(Integer productId) {
40         this.productId = productId;
41     }
42
43     public BigDecimal getPurchaseCost() {
44         return purchaseCost;
45     }
46
47     public void setPurchaseCost(BigDecimal purchaseCost) {
48         this.purchaseCost = purchaseCost;
49     }
50     private String manufacturerName;
51
52
53
54 }
55
56

Performance Trap using JPA: Transfer Object pattern and JPQL to the Rescue!

DISCLAIMER:  I am a Regular Average Java Programmer; an anti-expert.  I like to do things right, but I’m generally satisfied with doing things that WORK.  I’m sure there’s some JE (Java Expert) out there who knows how to do it right and you can buy his book and worship his rightness at the Java Rock Star Hall of Fame.

Can I say that I love JAX-WS with JPA with Netbeans?  This is a golden combination folks.  Netbeans supports the hell out of these things.  But there are some traps.  One of which is the potential for very poor performance.  But I will show you how to avoid this with a simple design pattern:   Transfer Object.

Transfer Object is so crucial when using JPA.  I realize that we should all know this, but Netbeans does not generate Transfer Objects for you like they do Controllers and Entities.  You have to do it yourself.  And you probably should have to.  After all, how can Netbeans anticipate the specific data transfer needs of your crappy application?

Let’s break it down!

What is a Transfer Object?

Here’s a pretty comprehensive technical breakdown from java.sun.com  (he he…sun)

http://java.sun.com/blueprints/patterns/TransferObject.html

Now, let’s just put it into RAJP terms.  A Transfer Object (or Value Object) is just the attributes needed for a particular use case all wrapped up together in one object.

What Problems does it solve with JPA?

  1. Separation of the concerns of the Model with the View
  2. Poor performance due to Network Traffic
  3. Poor performance due to High Latency

In Java Persistence API (JPA), your basic representation of a row in the database is called an Entity.  An Entity is a special kind of Java Bean that knows a lot about how to map a database table to an object.  So it’s not just instance variables, getters, and setters.  It’s a powerful little guy that you don’t want just any tier of your enterprise to have access to.    It’s also an expensive little guy.  In fact, depending on how it relates to other entities it might not be so little at all.  One entity that is joined with other entities might pull in a whole universe of data. And worse, it might even be like a House of Mirrors; creating an infinite graph of data.  AHHHHHHH!!!  Let me out of here!!!!

For example, a Car might have a list of Dealers and a Dealer might have a list of Cars each of which has a list of Dealers, and so on!  Fortunately, JPA implementations do not infinitely load this stuff.  The problem only arises when you need to expose Entities to another tier or another application (say, with web services).

[Who am I kidding?  I don't REALLY have tiers!!  Everything I do is in the web tier!  But I do have services!]

How do I do it?  “Is it magic?” you ask.  NO!!! It’s JAVA!  Nothing magical about it!  What do you think this is?  Ruby?

So, the idea is that you create these Transfer Objects with only the attributes that are required for the particular use case.    This separates the concerns of the Model from the View and minimizes network traffic, but it doesn’t necessarily solve the latency issue.  If your JPA calls are still retrieving and mapping gobs and gobs of data before you perform your transfer, then you may want to consider coding a more efficient JPQL query (or a stored procedure) and map the results directly into your Transfer Object.

Let’s look at how Netbeans builds entities and the inherent problems when it come to the way they handle web services.

Here’s an example of an Entity generated from a table in a relational database:


1
/*

 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5
 6 package sample.persistence;
 7
 8 import java.io.Serializable;
 9 import java.math.BigDecimal;
 10 import java.util.List;
 11 import javax.persistence.Basic;
 12 import javax.persistence.CascadeType;
 13 import javax.persistence.Column;
 14 import javax.persistence.Entity;
 15 import javax.persistence.Id;
 16 import javax.persistence.JoinColumn;
 17 import javax.persistence.ManyToOne;
 18 import javax.persistence.NamedQueries;
 19 import javax.persistence.NamedQuery;
 20 import javax.persistence.OneToMany;
 21 import javax.persistence.Table;
 22
 23 /**
 24  *
 25  * @author david ctr wilson-bur
 26  */
 27 @Entity
 28 @Table(name = "PRODUCT", catalog = "", schema = "APP")
 29 @NamedQueries({
 30     @NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p"),
 31     @NamedQuery(name = "Product.findByProductId", query = "SELECT p FROM Product p WHERE p.productId = :productId"),
 32     @NamedQuery(name = "Product.findByPurchaseCost", query = "SELECT p FROM Product p WHERE p.purchaseCost = :purchaseCost"),
 33     @NamedQuery(name = "Product.findByQuantityOnHand", query = "SELECT p FROM Product p WHERE p.quantityOnHand = :quantityOnHand"),
 34     @NamedQuery(name = "Product.findByMarkup", query = "SELECT p FROM Product p WHERE p.markup = :markup"),
 35     @NamedQuery(name = "Product.findByAvailable", query = "SELECT p FROM Product p WHERE p.available = :available"),
 36     @NamedQuery(name = "Product.findByDescription", query = "SELECT p FROM Product p WHERE p.description = :description")})
 37 public class Product implements Serializable {
 38     private static final long serialVersionUID = 1L;
 39     @Id
 40     @Basic(optional = false)
 41     @Column(name = "PRODUCT_ID")
 42     private Integer productId;
 43     @Column(name = "PURCHASE_COST")
 44     private BigDecimal purchaseCost;
 45     @Column(name = "QUANTITY_ON_HAND")
 46     private Integer quantityOnHand;
 47     @Column(name = "MARKUP")
 48     private BigDecimal markup;
 49     @Column(name = "AVAILABLE")
 50     private String available;
 51     @Column(name = "DESCRIPTION")
 52     private String description;
 53     @JoinColumn(name = "PRODUCT_CODE", referencedColumnName = "PROD_CODE")
 54     @ManyToOne(optional = false)
 55     private ProductCode productCode;
 56     @JoinColumn(name = "MANUFACTURER_ID", referencedColumnName = "MANUFACTURER_ID")
 57     @ManyToOne(optional = false)
 58     private Manufacturer manufacturer;
 59     @OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
 60     private List<PurchaseOrder> purchaseOrderList;
 61
 62     public Product() {
 63     }
 64
 65     public Product(Integer productId) {
 66         this.productId = productId;
 67     }
 68
 69     public Integer getProductId() {
 70         return productId;
 71     }
 72
 73     public void setProductId(Integer productId) {
 74         this.productId = productId;
 75     }
 76
 77     public BigDecimal getPurchaseCost() {
 78         return purchaseCost;
 79     }
 80
 81     public void setPurchaseCost(BigDecimal purchaseCost) {
 82         this.purchaseCost = purchaseCost;
 83     }
 84
 85     public Integer getQuantityOnHand() {
 86         return quantityOnHand;
 87     }
 88
 89     public void setQuantityOnHand(Integer quantityOnHand) {
 90         this.quantityOnHand = quantityOnHand;
 91     }
 92
 93     public BigDecimal getMarkup() {
 94         return markup;
 95     }
 96
 97     public void setMarkup(BigDecimal markup) {
 98         this.markup = markup;
 99     }
100
101     public String getAvailable() {
102         return available;
103     }
104
105     public void setAvailable(String available) {
106         this.available = available;
107     }
108
109     public String getDescription() {
110         return description;
111     }
112
113     public void setDescription(String description) {
114         this.description = description;
115     }
116
117     public ProductCode getProductCode() {
118         return productCode;
119     }
120
121     public void setProductCode(ProductCode productCode) {
122         this.productCode = productCode;
123     }
124
125     public Manufacturer getManufacturer() {
126         return manufacturer;
127     }
128
129     public void setManufacturer(Manufacturer manufacturer) {
130         this.manufacturer = manufacturer;
131     }
132
133     public List<PurchaseOrder> getPurchaseOrderList() {
134         return purchaseOrderList;
135     }
136
137     public void setPurchaseOrderList(List<PurchaseOrder> purchaseOrderList) {
138         this.purchaseOrderList = purchaseOrderList;
139     }
140
141     @Override
142     public int hashCode() {
143         int hash = 0;
144         hash += (productId != null ? productId.hashCode() : 0);
145         return hash;
146     }
147
148     @Override
149     public boolean equals(Object object) {
150         // TODO: Warning - this method won't work in the case the id fields are not set
151         if (!(object instanceof Product)) {
152             return false;
153         }
154         Product other = (Product) object;
155         if ((this.productId == null && other.productId != null) || (this.productId != null && !this.productId.equals(other.productId))) {
156             return false;
157         }
158         return true;
159     }
160
161     @Override
162     public String toString() {
163         return "sample.persistence.Product[productId=" + productId + "]";
164     }
165
166 }
167
168

Note that there are several joins with other entities.  Well each of those entities join back to Product!  This is helpful stuff, but there is the trap!  Do not try to return this entity from a web service and do not try to replicate these relationships in your Transfer Object!  And DON’T CROSS THE STREAMS!!!!!!

Here’s what will happen:

com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML

OH SNAP!!!  Whoa!!!  A bottomless pit of XML.  That sounds scary.  And I bet if you DID reach the bottom it would not be a soft landing.  XML is hard and scratchy!!!

Imagine with me a simple use case where a web application needs to show a Product catalog.  All you really need is Product Id (for retrieval purposes), Description, Cost,  and the name of the Manufacturer.  You might not want your web app to expose the Markup, the Quantity on Hand or other details.  So you design ProductTO (TO for TransferObject)  with only the fields needed for the catalog listing.


 1 /*
 2  * To change this template, choose Tools | Templates
 3  * and open the template in the editor.
 4  */
 5
 6 package sample.persistence;
 7
 8 import java.math.BigDecimal;
 9
10 /**
11  *
12  * @author david ctr wilson-bur
13  */
14 public class ProductTO {
15     private Integer productId;
16     private String description;
17     private BigDecimal purchaseCost;
18
19     public String getDescription() {
20         return description;
21     }
22
23     public void setDescription(String description) {
24         this.description = description;
25     }
26
27     public String getManufacturerName() {
28         return manufacturerName;
29     }
30
31     public void setManufacturerName(String manufacturerName) {
32         this.manufacturerName = manufacturerName;
33     }
34
35     public Integer getProductId() {
36         return productId;
37     }
38
39     public void setProductId(Integer productId) {
40         this.productId = productId;
41     }
42
43     public BigDecimal getPurchaseCost() {
44         return purchaseCost;
45     }
46
47     public void setPurchaseCost(BigDecimal purchaseCost) {
48         this.purchaseCost = purchaseCost;
49     }
50     private String manufacturerName;
51
52
53 }
54
55

One last convenience is to make a transfer method in your Entity class.

166     public ProductTO transfer(){
167         ProductTO to = new ProductTO();
168         to.setProductId(productId);
169         to.setDescription(description);
170         to.setPurchaseCost(purchaseCost);
171         to.setManufacturerName(this.manufacturer.getName());
172         return to;
173     }

The TransferObject solves the first two problems, but leaves the issue of latency.  When you retrieve a Product list, you are also retrieving all the entities joined to it.  Even if you configured the entity with lazy loading, you would still load Manufacturer entity when you try to access the manufacturer name in your transfer method.  Imagine THAT scenario compounded with multiple joins and large datasets.

Get the picture?

This is where some Java Persistence Query Language (JPQL) comes in handy.

SELECT p.productId, p.description, p.purchaseCost, p.manufacturer.name FROM Product p

Map this result set to your ProductTO and you solve your problems.


258
public List<ProductTO> findProductCatalog() {

259         EntityManager em = getEntityManager();
260         List<ProductTO> productTOs = new ArrayList<ProductTO>();
261         try {
262             Query q = em.createQuery("SELECT p.productId, p.description, p.purchaseCost, p.manufacturer.name FROM Product p");
263             List<Object[]> products = (List<Object[]>)q.getResultList();
264             for (Object[] objects : products) {
265                 ProductTO to = new ProductTO();
266                 to.setProductId((Integer) objects[0]);
267                 to.setDescription((String) objects[1]);
268                 to.setPurchaseCost((BigDecimal) objects[2]);
269                 to.setManufacturerName((String) objects[3]);
270                 productTOs.add(to);
271             }
272             return productTOs;
273         }
274         finally {
275             em.close();
276         }
277     }

Yes, I know this kind of defeats the purpose of automated ORM (Object Relational Mapping), but…

RAJP – [raj-pee] Just one of the thousands of regular, average java programmers trying to get their job done…

Javaone 2010!!!

Time to start blogging again.  My employer has cracked down on some of the blogging practices around here and I just didn’t want to be caught in that net.   I will be blogging my experience at Javaone/Oracle Develop this year from the perspective of a RAJP.  I’ll be travelling with a few other RAJPs and one not-so-average youngin.   When the last afternoon session is done, he’ll be the one who continues eating and crapping programming while we eat and crap the local pub food!   Mmmmmmmmmmm, fish n chips and bangers and mash at Foley’s!

Exterior Image #2