Thursday, December 22, 2011

Associating JSP Editor for the .xhtml extension in Eclipse

To use the eclipse JSP editor for editing .xhtml files (created for JSF), go to Window > Preferences > General > Content Type > Text > JSP and add *.xhtml in the File Associations section.
With this extension added, you shall be able to see the available tags & attribute listing for the JSF tags too.

Monday, May 16, 2011

Setting timeout for web service invocations using SII client generated using Weblogic 8.1 SP6 ANT task

Even though the 11g version of weblogic has been released, most of the big organizations continue to use BEA Weblogic 8.1 version (there are number of reasons and I won't get into details). Since we have been invoking some very busy web services and wanted to utilize the timeout mechanism to throw an exception on the client side so that the user may be requested to try at a later time rather than waiting for ever. Over a number of blogs I saw people suggesting the use of weblogic.webservice.rpc.timeoutsecs property and provide the timeout values in seconds. It didn't seem to work for me and so was the experience of many users using the webservice client generated by weblogic ant tasks and using the weblogic.jar and webservice.jar in classpath. After a number of google searches, I found out a person who had succesfully used the above mentioned property to get the timeout functionality working. The secret to this person's solution was, he had used a DII (i.e. used a self written client instead of the generated client). The sample DII client for a Calculator service with an add webmethod is as below:
      String NS_XSD = "http://www.w3.org/2001/XMLSchema";
      String targetNamespace = "http://www.bea.com/examples/Calculator";

      System.setProperty("javax.xml.rpc.ServiceFactory", "weblogic.webservice.core.rpc.ServiceFactoryImpl");
      System.setProperty("weblogic.webservice.verbose", "false");
      System.setProperty("weblogic.webservice.UseWebLogicURLStreamHandler", "true");

      ServiceFactory factory = ServiceFactory.newInstance();
      QName serviceName = new QName(targetNamespace, "CalculatorService");
      QName portName = new QName(targetNamespace, "CalculatorServicePort");
      QName operationName = new QName(targetNamespace, "add");
      Service service = factory.createService(serviceName);

      Call call = service.createCall();
      call.setOperationName(operationName);
      call.setPortTypeName(portName);
      call.setProperty(Call.OPERATION_STYLE_PROPERTY, "rpc");

      call.addParameter("intVal", new QName(NS_XSD, "int"), Integer.class, ParameterMode.IN);
      call.addParameter("intVal0", new QName(NS_XSD, "int"), Integer.class, ParameterMode.IN);
      call.setReturnType(new QName(NS_XSD, "int"), Integer.class);
      call.setTargetEndpointAddress("http://localhost:7001/CalculatorService/CalculatorService");
      ((weblogic.webservice.core.rpc.CallImpl) call).setProperty("weblogic.webservice.rpc.timeoutsecs", "5");
      System.out.println("Invoked DII :");
      System.out.println("Result : " + call.invoke(new Object[] { new Integer(a), new Integer(b) }));
Now comes the second problem, all the existing client code for a huge number of webservices are SII codes (generated by the ANT task in webservices.jar). Instead of converting all the client codes to DII, I had to find the solution using SII. Since the code is not provided by BEA, I decompiled the jar to understand what's going on under the hood and found something strange, the weblogic.webservice.rpc.timeoutsecs set as a system property was fetched inside the jared code (in webservices.jar) but was only used in the logic that handled https invocations (may be missed out looking at the right place or it was never there). In order to confirm my findings, I exposed the service over https and modified the client code with some additional properties (related to https invocations and nothing to do with web service in particular) and VOILA!!!! It worked :)

Inference: To use the timeout property for rpc calls when using client generated SII, the webservice should be exposed in https (can't change the code in the jars used by the client code to fix it as the code is not open source). Or write a DII (example given above). For SII invocation over https you need to use the below mentioned properties:
       
System.setProperty("weblogic.security.SSL.trustedCAKeyStore", "C:/bea/weblogic81/server/lib/DemoIdentity.jks");
System.setProperty("weblogic.webservice.client.ssl.strictcertchecking", "false");
System.setProperty("weblogic.webservice.rpc.timeoutsecs", "10");
For invocations over https you shall need jsafeFIPS.jar & webserviceclient+ssl.jar in classpath in addition to webservices.jar & weblogic.jar (you can find all of those in the weblogic's lib folder). The invocation may also ask for license files (don't know why), then even put the license.bea & license_scale_limited.bea in the classpath.

For Weblogic 9 versions, the property to be set has changed. More details can be found at http://download.oracle.com/docs/cd/E13222_01/wls/docs92/webserv/client.html. Those properties are:
((Stub)service_action)._setProperty("weblogic.wsee.transport.read.timeout", 5000); //values are in millis
((Stub)service_action)._setProperty("weblogic.wsee.transport.connection.timeout", 5000); //values are in millis
Similiar properties for Weblogic 10 can be found at http://docs.oracle.com/cd/E13222_01/wls/docs100/webserv/client.html I hope you found this post helpful.

Thursday, April 7, 2011

Stop waiting for the designer to create rounded corners !!!

How many times has it happened that you've been waiting for the designer to create and provide you with the rounded corners image? We usually use these images as background images for divs or a rounded corner table. Now this can be achieved by using pure CSS. Follow the link http://www.css3.info/preview/rounded-border/ for more details. These CSS styles work perfectly for firefox and chrome but can give some problems on IE.

Saturday, March 12, 2011

jQuery FlexGrid & Spring MVC 3

Recently I have been working on Spring MVC 3. There is inbuilt support for returning JSON data using @ResponseBody annotation. Just make sure that jackson-all-x.x.x.jar is on your classpath. I used jackson-all-1.7.4.jar.This works great.

I wanted to display the results in a tabular format with some basic sorting and paging functionality with AJAX. So I thought I will give a shot at jQuery. jQuery is such an amazing JavaScript library it makes this a lot easier when it comes to working with JavaScript or manipulating DOM.

I found this amazing jQuery plugin, FlexGrid. It was pretty much what I wanted. Though it does not support i18N or themed L&F, it did the job for me.

So I started integrating the pieces. jQuery FlexGrid expects the JSON data to be in a specific format:

   total: (no of rec)
   page : (page no)
   rows : [{id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]},
           {id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]}
          ]

But the data returned from the method with @ResponseBody annotation is in the following format:

   
{(col1 value) , (col2 value) ,..}

So I thought I might as well go ahead and modify my DAO's to return the data in the required format. But well, why should I modify my DAO's? Its after all a UI layer requirement. This is what I came up with.

Write a wrapper class that will hold the data required for FlexGrid and send this as a JSON response. Here's the wrapper class:

import java.io.Serializable;
import java.util.List;

/**
 * Wrapper class for JSON data to send to the client.
 * 
 * Currently we are using jQuery FlexGrid for displaying JSON data in table.
* * jQuery FlexGrid plug-in requires data to be in the below specified format. * * * total: (no of rec) * page : (page no) * rows : [{id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]}, * {id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]} * ] * * To keep the data service independent of this requirement as far as possible, * the id, cell format specifically ignored. we wrap the result from the data * service and further format the result using JavaScript as required. * * * @author Enterprise Integrals * * @version 1.0 * @see jQuery FlexGrid * * @param T generic data type for list of objects to be sent in the JSON response. */ public class JsonDataWrapper<T> implements Serializable { private static final long serialVersionUID = 1L; //current page private int page; //total number of records for the given entity. private long total; //list of records to be displayed. private List<T> rows; public JsonDataWrapper(int page, long total, List<T> rows) { this.page = page; this.total = total; this.rows = rows; } // getter setter }
Here is how it is used in Spring MVC 3
/**
* FlexGrid submits the following parameters
* page: current page
* rp: rows per page
* sortname: sorting done on which column:
* sortorder: sort order asc/desc
* query: search criteria if you are using search option
* qtype: search on which column in grid. this is again customizable.
* 
* These parameters can be used as filters in the DAO to get the data.
*
* By default the FlexGrid uses POST. You can change to GET.
* @param T the entity list to displayed in grid
*/
@RequestMapping(value="/some Path", method= RequestMethod.POST)
public @ResponseBody JsonDataWrapper<T> getRows(WebRequest request) {
 //get the current page posted from the grid.
 int page = Integer.parseInt(request.getParameter("page"));
 //get the list of objects to be displayed from the db calling the service
 //the total number of pages are dynamically calculated on the basis of the total number of rows in the table. get that.
 JsonDataWrapper<T> jdw = new JsonDataWrapper<T>(page, total rows, rows);
 return jdw;
}
But there is a catch here. The FlexGrid plugin again refuses to render the data. The reason is the List<T> rows is again a list of objects returned from the DAO layer. It does not format the data as required by FlexGrid plugin. How do we do that? So I decided lets not put this logic in our MVC implementation. Here is how the data is set on to the FlexGrid using JavaScript.

 
$("#flex1").flexigrid({
   // standard flexgrid configuration as per your need,
   preProcess: formatData
});

Note the preProcess definition. It pre processes the data before the grid is populated with the JSON data return from the server. You can inline the function that actually formats the data but I kept it separate. Here it goes:

function formatData(data) {
 var rows = Array();
 $.each(data.rows,function(i,row){
                //id can be mapped to any attribute of the return object in the list
  rows.push({id:row.val1, cell:[row.val1,row.val2]});
});
 
 return {
  total:data.total,
  page:data.page,
  rows:rows
 };     
}

Now the grid populated correctly. There are other grid plugins for jQuery but FlexGrid & jQGrid are the best. FlexGrid has lot less functionality as compared to jQGrid but I like it because its light. For advanced features you can have a look at jQGrid.

Sunday, February 20, 2011

PHP 5.3 Date Timezone issue

I was recently trying to setup PHP on my development machine. I downloaded the php-5.3.5-Win32-VC6-x86.zip for Windows and started to manually configure PHP (to get a feel. You can ofcourse use something like XAMPP to get started quickly.)

Then I quickly executed some PHP scripts and found everything was running fine. I dumped some of the PHP samples I had and played around until one started complaining

It is not safe to rely on the system's timezone settings.

Little researching solved the issue. PHP 5.3 requires you to set date.timezone in php.ini file

e.g. date.timezone = Asia/Calcutta

http://nl3.php.net/manual/en/timezones.php