Tuesday, October 30, 2012

Registering Custom JSF Renderer

JSF has a very flexible architecture by providing hooks to plugin custom implementation for components, renderers, converters, validators etc. Today i will discuss the way to plugin own renderer without touching any other thing. Usually in every application, there are some properties which are set for ui components in order to make look & feel consistent throughout the application and these properties are set on each page for components. If we override renderer and set these properties as default properties, a lot of burden from developers end is removed. Moreover, it will also provide an easy way to change it in future at a single point instead of each page, so this is very handly thing to provide own renderers.
I am overriding a renderer for input text component of Prime faces. This renderer will not do anything special and will just print a statement on console. Here are the steps to follow:

  • First override the renderer of the component in which we want to provide custom rendering. Prime faces' User guide is an excellent reference source for each component e.g. for InutText, you will find all information about component's implementation classes and you will find there that org.primefaces.component.inputtext.InputTextRenderer is a default renderer for prime faces' input text component.



  • Create a custom renderer class which will extend above renderer and override the method in which you want to provide custom implementations. You can also download source code and can study default implementation of renderer. It will provide you good understanding how to do things. Sample implementation is given below:
     public class MyInputTextRenderer extends InputTextRenderer{
    @Override
     protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
        System.out.println("encodemarkup");
        super.encodeMarkup(context, inputText);
    }
    }
              • Third and last thing is to register this custom renderer in jsf application. For that you will have to provide following entries in faces-config.xml:

                 
              component-family and renderer-type will help framework to understand for which component, custom renderer will be used

                          Saturday, October 6, 2012

                          Maven Tips


                          • When we include a jar dependency in pom.xml. That jar may intern depend on other jars and maven resolve it and loads all jars whether those are directly indicated as dependent jars or indirectly within dependent jars. Now if we have some latest version or any other reason and want to exclude a particular jar to be included as dependent then maven provides "exclusions" element tag. Its sample usage is given below:
                          <dependency>
                          <groupId>org.hibernate</groupId>
                          <artifactId>hibernate-core</artifactId>
                          <version>4.1.7.Final</version>
                          <scope>provided</scope>
                          <exclusions>
                                <exclusion>
                                   <groupId>org.antlr</groupId>
                                   <artifactId>antlr</artifactId>
                                </exclusion>
                             </exclusions>
                          </dependency>

                          In above example, exclusions tag used to exclude antlr jar file to be included as dependent jar for hibernate

                          continued...

                          Monday, November 14, 2011

                          Common ADF Mistakes - Conversion pages to page fragments

                          Suppose you have developed ADF task flow with pages (not page fragments) and later on you decide that these pages should be page fragments, and you convert that taskflow to support page fragments. After conversion, if you get this error
                          java.lang.IllegalStateException: Attempt to validate an already invalid RegionSite:
                          Check whether you have used PageController for page or not. If you used then convert it to RegionController. ADF does not give you indication of this. If you want to debug error, do the following:
                          • Goto bindings of page on which you dropped taskflow containing page fragments.
                          • In Executables, click the taskflow and set its property "activation" to "immediate"
                          • Now run and you will get detailed error.
                          Update

                          It can also occur if your taskflow is calling any method before page loading and that method is throwing some error.

                          Sunday, March 13, 2011

                          JSF 2 Internals - Efficient way of Redirecting to a Page

                          There are certain cases where you are needed to redirect  to a different page than requested by user e.g. if user has requested a secure page for which he/she is not authorized, your application will have to redirect to login page or some other page. I have created a utility method to redirect to a page. You can call anywhere but for example given above, you can call it a beforePhase method of RestoreViewPhaseListener. Here is the method code:

                          public static void redirect(String viewId) {

                          execute(FacesContext.getCurrentInstance(), viewId);
                          }


                          private static void execute(FacesContext facesContext, String viewId)
                          throws FacesException {

                          UIViewRoot viewRoot = null;
                          ViewDeclarationLanguage vdl = facesContext.getApplication()
                          .getViewHandler()
                          .getViewDeclarationLanguage(facesContext, viewId);

                          if (vdl != null) {
                          // If we have one, get the ViewMetadata...
                          ViewMetadata metadata = vdl.getViewMetadata(facesContext,
                          viewId);

                          if (metadata != null) { // perhaps it's not supported
                          // and use it to create the ViewRoot. This will have, at
                          // most
                          // the UIViewRoot and its metadata facet.
                          viewRoot = metadata.createMetadataView(facesContext);

                          }
                          }

                          facesContext.setViewRoot(viewRoot);
                          facesContext.renderResponse();
                          assert (null != viewRoot);

                          }

                          viewId is the name of page to which it should redirect e.g. "/redirect.xml" (assuming page is at root level). Inside execute method, you get the ViewDeclarationLanguage which is page type specific e.g. if page is in facelet markup, you get DefaultFaceletViewDeclarationLanguage and if page is in JSP markup, then you will get corresponding ViewDeclarationLanguage. After this, page root tree is constructed by calling createMetadataView if it is not already constructed. Finally set the new ViewRoot and call renderResponse method, which will bypass all phases and will jump directly to render phase.

                          Tuesday, March 8, 2011

                          JSF 2 Internals - Configurations

                          In JSF 2, there is almost no need to mention any configuration in a small application and defaults values are sufficient enough to fulfill the purpose. All the default configurations are in com.sun.faces.WebConfiguration. As i mentioned in my previous blog post, JSF has implemented ServletContainerInitializer which is new interface in Servlet 3.0 in order to register servlets and other stuff programmatically at the time of loading application. In 'onStartUp' method, it adds listener com.sun.faces.ConfigureListener. It implements various interface listeners like ServletRequestListener, HttpSessionListener, ServletContextListener, ServletRequestAttributeListener, HttpSessionAttributeListener, ServletContextAttributeListener. Most important for loading configuration is ServletCotextListeenr which has two methods contextInitialized and contextDestroyed. contextInitialized  is called when application loads and ServletContext is created, so this is the best time to load configurations in JEE web applications. JSF 2 also gets benefit of this and creates WebConfiguration Object and loads default values for configurations. If application has its own values mentioned in web.xml, they are overriden.

                          Wednesday, March 2, 2011

                          JSF 2 Internals - Entry of FacesServlet is optional

                          In JEE 6, major milestone achieved was reduction of configuration files e.g. in servlet based web application, no need to mention web.xml and application assumes default configuration settings. Same thing was also achieved in JSF 2. Now there is no need to mention FaceServlet or servlet mapping in web.xml. But question arises from where application picks these defaults? Answer is the "ServletContainerInitializer" interface which allows a library/runtime to be notified of a web application's startup phase and perform any required programmatic registration of servlets,filters, and listeners in response to it. Inside of "onStartup" implementation of JSF 2, all these defaults are set, Sample code is given below:
                          ServletRegistration reg =
                          servletContext.addServlet("FacesServlet",
                          "javax.faces.webapp.FacesServlet");
                          reg.addMapping("/faces/*", "*.jsf", "*.faces");
                          servletContext.setAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED, Boolean.TRUE);
                          JSF 2 class which implements this interface is "FacesInitializer" class and have been mentioned under jsf-ri.jar's META-INF/services folder.



                          Thursday, February 24, 2011

                          Learning IOS Programming for Java Developers - Memory Management in Setters and Getters Of Object

                          Encapsulation is one of the basic building block in Object Oriented paradigm. Encapsulation in Java is achieve by restricting user to directly access the fields of Object and in order to access those fields, setters and getters are written. Objective C is also an object oriented programming language and also provides encapsulation by providing setters and getters to access the object data. Here is the sample class which contains two fields. One is an object and second one is of basic data type.
                          @interface TestClass : NSObject
                          {
                          NSString *name;
                          int id;
                          }

                          - (void) setName : (NSString *) newName;
                          - (NSString *) name;

                          - (void) setId : (int) newId;
                          - (int) id;

                          "setName" and "name" is setter and getter of "name" field. Similarly "setId" and "id" id setter and getter of "id" field.

                          Here is the implementation part of class
                          @implementation TestClass
                          {
                          - (void) setName : (NSString *) newName
                          {
                          [newName retain];
                          [name release];
                          name = newName;
                          }

                          - (NSString *) name
                          {
                          return name;
                          }
                          - (void) setId : (int) newId
                          {
                          id = newId;
                          }

                          - (int) id
                          {
                          return id;
                          }


                          }

                          setName needs your special intention for memory management point of view. First you send message "retain" to parameter, then you release old field by sending message "release" to name pointer. Then you assign new value to name pointer. These three steps are critical because if you change the order like you release old one and then retain new parameter, if both are same, then by sending release message will free the memory and new parameter will also be freed because that was same as old one. By sending retain message to parameter, you actually gain ownership of it and its reference count increases. Since you have also ownership of old one, so you will have to release it otherwise you will lose reference and there will be memory leak. Now as a java developer i can think that if "name" field is null, then sending release message may give something like NullPointerException but in Objective C, sending a message to null is safe and it will not throw any error and will keep executing next line.
                          Now last thing which is missing is that how to release fields which are retained before releasing object memroy, so for that you will have to overwrite a special method of NSObject "dealloc". This method is called when you send release message to an object and its reference count is 0. In this method you will have to release all those objects which you have retained. Sample implementation for above class is given below:
                          - (void) dealloc
                          {
                          [name release];
                          [super dealloc];
                          }