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];
}


Wednesday, February 23, 2011

How to Learn IOS Programming having experience In Java language

I am creating this post to help those which are working in java programming language and want to explore or work in IOS. I am working in Java for last eight years and now exploring IOS programming so will share my experiences through this post.

Monday, February 7, 2011

Setting datasource name programmatically for ADF Application

While working on an enterprise application for my client, i received a request from the client that data source name should not be hardcoded in the application and it should be configurable because client wants to deploy it more than one instance of application on the same server for different purposes like preview, production etc. So i googled it, and found excellent article 11g Dynamic JDBC Credentials for Model 1, Struts, Trinidad, and ADF Faces Rich Client
Here it is simplified version:
You will have to extend two following classes:

  • EnvInfoProvider
  • DefaultSessionCookieFactory

EnvInfoProvider
This is main interface and datasource name will be set in the implementation of this interace. You will have to implement following three methods:

  • public Object getInfo(String propName, Object object)
  • public void modifyInitialContext(Object initialContext)
  • public int getNumOfRetries()
Only important method for our scenario is getInfo method. It is used to set new datasource name. Sample implementation is given below:

public Object getInfo(String propName, Object object) {
String myDataSourceName = "test"; // You can set it through your logic
if (object instanceof Hashtable) {
Hashtable connectionEnv = (Hashtable)object;
System.out.println(connectionEnv.get(Configuration.JDBC_CONNECTION_NAME));
String contextPath = (String)ADFContext.getCurrent().getSessionScope().get("contextPath");
connectionEnv.put(Configuration.JDBC_DS_NAME,"java:comp/env/jdbc/"+myDataSourceName );
}
return null;
}

public void modifyInitialContext(Object initialContext) {
}

public int getNumOfRetries() {
return 0;
}

DefaultSessionCookieFactory
In order to configure custom implementation of EnvInfoProvider, you will have to extend DefaultSessionCookieFactory and override createSessionCookie method. Sample implementation is given below:
public SessionCookie createSessionCookie(String name,
String value,
ApplicationPool pool,
Properties properties) {

SessionCookie cookie = super.createSessionCookie(name, value, pool, properties);
Hashtable env = pool.getEnvironment();

env.remove(Configuration.JDBC_CONNECTION_NAME);
EnvInfoProvider provider = new MyEnvInfoProvider();
cookie.setEnvInfoProvider(provider);
return cookie;
}
Now last step is to configure this custom SessionCookieFactory. Open bc4j.xcfg of application module and add following element as a child of respected AppModuleConfig element