Recent Changes - Search:


SourceForge Logo









YourKit Java Profiler

Concepts

The Big Picture

Most applications require profiling, in the sense that you want the behavior to be different for different "types" of users. This is the regular "user roles", "groups", "privileges", etc. vocabulary that you have to deal with in almost every application you develop... As a matter of fact this is a growing concern, more and more applications require to support multiple users with different profiles. The game is always more or less to provide customized views and interactions between Domain Objects and End-Users, depending on their profile.

JFacets is all about associating code (facets) to some profiles (and possibly some object types) at development-time, and being able to retrieve this code at run-time for some given profiles (and target objects). It aims at providing reusable solutions to the recurrent issue of user profiling.

The framework provides the base building blocks to :

  • encapsulate your users/roles/groups/etc. and make them available in the facets world as a graph of profiles;
  • write facet classes, and assign them to profiles (and possibly target object types) ;
  • retrieve the appropriate facets into the code at run-time, based on the requesting profile (and possibly target object or target type).

One important thing
JFacets handles facet retrievement and instanciation for you (and possibly execution - explained later in this page), but that's where it ends. It's your responsability to make use of the facets to suit your needs. Facets have many fields of application, virtually everywhere you need profiling, so you can imagine it's wide... You can have a look to WebFacets for a concrete example of use : it's an extension of JFacets that allows to make use of facets in J2EE web environments, with practical examples (like profile-based GUI rendering).

Let's start by the beginning, and have a look at the way profiles are handled in JFacets.

Mapping The Profiles

The first thing in JFacets is profiles : they are the foundation for the framework.

JFacets relies on the ProfileRepository concept in order to encapsulate the users/roles/groups/etc. in a generic way. This component has to implement a very simple interface that allows JFacets to navigate the profiles graph and find facets associated to some profiles, independently of the underlying user management logic.

IProfileRepository :

public interface IProfileRepository {

        /**
         * Return a profile by its ID
         */

        IProfile getProfileById( String profileId );

        /**
         * Return passed profile's parents in an array
         */

        IProfile[] getSuperProfiles( IProfile profile );

}

As you can see, it allows JFacets to :

  • retrieve a profile by its ID ;
  • get parents of a given profile.

Basically, in order to use JFacets in your application, you have to implement this interface to wrap your users/roles system, and inject it using Spring. Then, JFacets knows about the Profiles Graph, and you can define and retrieve facets for your own users and roles/groups/etc.

NOTE
Once again, the ProfileRepository is a cornerstone of the framework, but for the moment you don't really need to know more than what you can read above. For a more advanced description of the ProfileRepository, have a look here.

Assigning Facets To Profiles And Object Types

The main idea in JFacets is that you assign the facets to application profiles, and possibly target object types. This means that, when you create a facet, you have to specify :

  • the symbolic name of the facet (allows to distinguish facets assigned to the same profile and object type) ;
  • the profile you assign the facet to ;
  • the type of the target object (a Java Class or Interface, which actually defaults to Object.class if not specified).

This is the base information that is required in order to create a facet.

Writing The Facets

Once gain, a facet can be anything. It can be a POJO (with a default constructor), or it can implement the net.sourceforge.jfacets.IFacet interface :

public interface IFacet {

        public void setContext(IFacetContext ctx);

        public IFacetContext getContext();

}

As you can see, it only makes your object context-aware : you'll be able to get access to the facet context in the facet's code. But once again, a plain java class could also be facetized.

Amongst other ways, you can use Java5 annotations in order to define your facets. The example below shows two facetized POJOs, with their assignation details specified using JFacet's @FacetKey annotation.

@FacetKey(name="doStuff", profileId="ROLE_USER", targetObjectType=MyClass.class)
public class DoStuff {

  public String doSomething() {
    ...
  }

}

@FacetKey(name="doStuff", profileId="ROLE_ADMIN", targetObjectType=MyClass.class)
public class DoStuffAdmin extends DoStuff {

  @Override
  public String doSomething() {
    ...
  }

}

As you can see, DoStuffAdmin extends DoStuff and overrides doSomething(). Also, they are assigned to different profiles (ROLE_USER, and ROLE_ADMIN).

Have a look here for more infos about how to write facets and assign them to profiles/target types.

Retrieving Facets At Run-time

Once you have written your facets, you use them in your code to... do something profiled !

Basically, to retrieve a facet, you'll need the following stuff :

  • the name of the facet you want to get ;
  • the requesting profile ;
  • a target object (optional) ;
  • an instance of JFacets.

Here under is a code snippet showing how to retrieve one of the facets defined above for the current profile :

// the target object...
MyClass myObj = ... ;
// get profile Id (this uses your existing user management code)
String profileId = ... ;
// obtain the JFacets bean
JFacets jf = JFacets.get();
// get the facet
DoStuff facet = (DoStuff)jf.getFacet("view", profileId, myObj);
// use the facet
facet.doSomething();

As you can see, using facets is pretty easy. You also have a taglib in WebFacets in case you want to use facets in JSPs.

Have a look here for more infos about how to retrieve facets.

Handling Inheritance : Profiles And Types

Of course, JFacets handles inheritance of both profiles and types. This means that facets assigned to a given profile are also available to its sub-profiles, and that facets assigned to a given target object type (class or interface) is also available to its subtypes.

This allows facet overriding : you can specialize facets for subprofiles or target object subtypes. At run-time, JFacets performs a kind of dynamic facet dispatch (in comparison to dynamic method dispatch in OOP) : it selects the facet that's the closest to supplied profile and target object type (in the two inheritance graphs).

Facet overriding is very powerful : that's the heart of JFacets. The facet lookup algorithm is described here.

Summing It Up

This page explained the global concepts in JFacets. As you've seen, it's all about facets that are bound to profiles and object types, and used at run-time to do various profile-based tasks.

Basically, to use facets, you have to :

  1. Provide a ProfileRepository that encapsulates your user-management logic (users, roles, groups, etc.) ;
  2. Write facets and assign them to profiles and object types ;
  3. Write code that obtains facets (JFacets.getFacet()) and uses them.

In short, JFacets provides a framework to write profile-aware code in a consistent and efficient fashion. It provides a simple toolkit for Java applications that require profile-awareness.

Of course, it has a pretty wide scope and can be used in many situations (almost everywhere you want code to behave in a personalized fashion). That's why I'd recommend to have a look at the Examples, and why not read about WebFacets which has concrete examples of using facets in a web environment.

Edit - History - Print - Recent Changes - Search
Page last modified on May 11, 2007, at 07:42 AM