The Source for Java Technology Collaboration
User: Password:



Jacob Hookom's Blog

April 2006 Archives


Possible JSF Converter for EJB 3

Posted by jhook on April 20, 2006 at 11:50 PM | Permalink | Comments (8)

One of the nice things about some of this standardization in the JEE 5 stack is the possibility for more cohesive development. I don't think we've even scratched the surface of possibilities here for productive development with EJB 3 and JSF in combination.

One of the things that irks me a lot with web development is the need to pass identifiers around:

  1. Query the DB for a list of Widgets
  2. Render a list of Widgets, generating links to Widget Detail pages, by Widget Id
  3. On Widget Detail page, take the ID passed in the request and query for the specific Widget
  4. Display Widget Detail

So we go around passing things by ID. Unfortunately, JSF still suffers from this to some extent. What would be nice is to just have the Widget Detail page just take in a Widget object, without requiring me to do the translation back and forth by Widget's identifier

With JSF, we have the concept of a Converter, whose job it is to take some object and render it to the page, and then take whatever was rendered to the page and then produce an object. With this capability, don't you think we could automate the Widget->ID->Widget within our application?

<h:selectOneMenu value="#{detailView.widget}" converter="#{widgets.converter}">
  <f:selectItems value="#{listView.allWidgets}">
</h:selectOneMenu>

With the above code, I should be able to use the converter from #{widgets.converter} to do the Widget->ID->Widget transformation for me:

public Converter getConverter() {
    return new EntityConverter(this.entityManager, Widget.class);
}

As a luxury of EJB 3 standardization, I can implement my EntityConverter to figure out which field is the identifier and use it for the Converter.getAsString(...,Widget obj) and then be able to translate and fetch via the EntityManager in Converter.getAsObject(...,String id). With this, we would end up with a rendered output like:

<select id="wid" name="wid">
    <option value="34332">Topper Widget</option>
    <option value="34121">Whopper Widget</option>
    ....
</select>

And, the receiving action would just have a setter that looked like:

public void setWidget(Widget w) {
    this.widget = w;
}

Pseudo code for the EntityConverter:


public class EntityConverter implements Converter {
  private final EntityManager em;
  private final Class type;

  public String getAsString(FacesContext faces, UIComponent c, Object obj) {
    return this.getEntityId(this.type).getId(obj);
  }

  public Object getAsObject(FacesContext faces, UIComponent c, String id) {
    return this.getEntityId(this.type).getObject(id);
  }

  private static class EntityId {
    // abbr

    public String getId(Object obj) {
      return this.idField.get(obj).toString();
    }

    public Object getObject(String id) {
       Object obj = ConvertUtils.convert(id, this.idField.getType());
       return this.em.find(this.type, obj);
    }
  }

}

Thinking about security, we could implement global encoding of identifiers. I don't know about you, but a lot of times when writing web apps, you can either pass identifiers 'clear text' and then do authorization on each succeeding request, or 'encode' the identifiers up front which will guarantee a legit acceptance on a succeeding request.

<select id="wid" name="wid">
    <option value="A4FB39">Topper Widget</option>
    <option value="ABBE92">Whopper Widget</option>
    ....
</select>

So if we are able to look at the JCA API and setup some kind of secret key, per session, I can use the passed FacesContext to check the session for the key and use a simple crypto algorithm to encode/decode identifiers, all within that one SecureEntityConverter. For performance, you could include some kind of caching mechanism at the same scope as the secret key to quickly translate identifiers back and forth.

JSF-wise for performance, the EntityConverter.getAsString(..) is cheap and would be used when rendering lots of widgets to the client. The more expensive fetching by EntityConverter.getAsObject(..) would only be done for the parameter actually passed in the request-- which any solution/framework would have to do. Even in a niche condition, the collection of Widgets would have already been fetched and Persistence implementations would already have a transactional cache over finding a widget by id.

If someone were to implement this, I think it would be quite the gem in JSF's capabilities and basically 'automate' the constant flip flopping we have to do to accomodate client/server communication.



Constraint-Based Services with RPC

Posted by jhook on April 12, 2006 at 03:59 PM | Permalink | Comments (6)

The Concept

A while back, I started to write DAO's for an application at work; and of course we chose Hibernate. I've been on this 'K.I.S.S My App' kick lately with keeping things as simple as possible and actually leveraging APIs to their full extent. This theme was carried out so much so that the DAOs actually returned Criteria objects:

public class WidgetDao extends DaoService {

  public Criteria queryByCategory(long catId) {
    return this.getSession().createCriteria(Widget.class)
                  .add(Restrictions.eq("category.id",  catId);
  }

  public List findByCategory(long catId) {
    return this.queryByCategory(catId).list();
  }
}

So why the heck would I expose Criteria objects? Well, the answer is simple: I wanted to allow the most flexability at the point of most concern. So the DAOs expose this initial constraint over the data with whatever business/domain logic (the case above is really simple), but as to the what and how the data is returned, now the client of the DAO is free to decide.

This really came to light when creating UIs where we could gain Criteria instances, then assign projections, sorting, and additional filtering over the data without pressing this use case back onto my DAO/Services layer. The end result was highly efficient, agile, and fast data mining within the UI. No needless layers of complexity and procedural contracts with my service layers to expose the information I needed.

SOA, RPC, and AJAX

Let's apply this concept to SOA and RPC. Many of these new AJAX 'frameworks', and Action MVC frameworks in general, rely on pushing content around. You spend time building up these procedural contracts to expose data models, but there's no way to know what information is used and how the information will be used.

This blindness really comes to light when you are dealing with desparate systems with client/server or server/server architectures. You've written an RPC method to deliver a set of Widgets. Well, in your domain, Widgets have a lot of aggregate and composite relationships, how do you know what to expose and how to expose it to all clients? You may simply choose to push 2K of object graphs when all you needed was the Widget's ID and Description. So you begin to see the waste. This gets even more tricky when clients access to some of that aggregate data on Widgets, and if that fails in performance, are you going to write more RPC methods?

Some of the public SOA APIs from major vendors kind of do this with providing specialized parameters/attributes within their requests to specify client-based constraints such as, "Do you want short or long details on the product search?" (Amazon).

Possible Solution

Because we are blind to all possible use cases of our domain models and services, we come up with a way for the client to interrogate the data or add constraints to our RPC calls within the remote request itself. Ideally, this would be taken care of by some mediator framework such that the RPC could be invoked on the server, but based on the constraints provided by the client, we can selectively return "lighter" responses.

So take a Widget catalog exposed over SOA. We still have the RPC contract for security such that we apply initial constraints, but client could use XQuery or some other standard to specify how and what is being transported back over the network. How do you know all the possible ways of exposing your data model to a client? Wouldn't it be easier to just use some kind of mediator to query/filter/sort your data as each client needs it?

In terms of the UI, it would be conceivable to back this by a templating engine on the client such that a JavaScript Agent could pre-determine what data is presented and selectively query generic RPC services on the server.

Conclusion

It all comes down to a cost highlighted with network latency. Having objects in memory on the server is cheap, but we all know that XML/etc is horrible at efficiently representing object graphs and that network latency is an obvious crutch in thin-client applications. We alleviate this issue to some extent by coming up with an Agent-based solution on the client with a server-side mediator which will specify the what and how data is transported over the network. Keep in mind, the traditional push model for data can be both expensive to the client and server.

At JavaOne, we'll be talking about other approaches with AJAX and how component-oriented MVC (in general) not only supplements the complexity of UI constraints, but also is more agile than traditional approaches. JSF Avatar carries the torch in this context such that we've gone through the work, once, of defining our view and how the 'domain' of the UI relates; then we allow the client Agent to describe how it wants to interact with the view in an efficient and secure manner.





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds