YourKit Java Profiler |
JFacets /
ConceptsThe Big PictureMost 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 user profiles (and possibly some target objects) at development-time, and being able to retrieve this code at run-time. The framework provides the base building blocks to :
Let's start by the beginning, and have a look at the way profiles are handled in JFacets. Mapping The ProfilesThe 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.
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 :
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.
Assigning Facets To Profiles And Object TypesThe 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 :
This is the base information that is required in order to create a facet. Writing The FacetsA facet can be anything. It can be a POJO (with a default constructor), or it can implement the 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 (useful to e.g. inject other component into your facets). 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(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, Have a look here for more infos about how to write facets and assign them to profiles/target types. Retrieving Facets At Run-timeOnce 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 :
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 TypesOf 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 OOP's dynamic method dispatch) : 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 UpThis 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, in order to use facets, you have to :
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. |