Wednesday, July 28, 2010

Display tag - Opensource JSP paging library...


Paging is important part when we have much data to show at once. We need to do all hectic coding for paging, like keep the total count, then count total pages to be shown, keep total records per page etc... This is nothing new but repeating and it takes bit time. So why not use some lib which gives you all of this with basic tags?

Note from the homepage : "The display tag library is an open source suite of custom tags that provide high-level web presentation patterns which will work in an MVC model. The library provides a significant amount of functionality while still being easy to use."

Basic steps to use are:

1. Get the jar file from http://displaytag.sourceforge.net and put it in classpath.

2. In your JSP page write following import for taglib.

 <%@ taglib uri="http://displaytag.sf.net" prefix="display" %>  

3. Check the following code for displaying the list of Objects as table with paging. You can configure different propeties of table as below, also can define CSS classes for diff. tags.


 <display:table name="lstObject" defaultsort="1" pagesize="20" sort="external" partialList="true"   
     size="totalCount" uid="lstObject" id="myObject"  
             export="false" requestURI="<%=someUrl%>" class="data">   
               
             <!-- For detailed understanding for each property, check the link http://displaytag.sourceforge.net/1.2/configuration.html -->  
             <display:setProperty name="paging.banner.placement" value="both" />  
             <display:setProperty name="paging.banner.group_size" value="10" />      
             <display:setProperty name="paging.banner.no_items_found">  
                 <span class="lfloat">No {0} found.</span>  
             </display:setProperty>  
             <display:setProperty name="paging.banner.one_item_found">  
                 <span class="lfloat">One {0} found.</span>  
             </display:setProperty>              
             <display:setProperty name="paging.banner.all_items_found">  
                 <span class="lfloat">{0} {1} found, displaying all {2}.</span>  
             </display:setProperty>  
             <display:setProperty name="paging.banner.some_items_found">  
                 <span class="lfloat">{0} {1} found, displaying {2} to {3}.</span>  
             </display:setProperty>              
             <display:setProperty name="paging.banner.full">  
                 <div class="paging_footer">  
                     <div class="rfloat">  
                         <div class="lfloat" style="padding-top:6px;">[<a href="{1}">First</a> | <a href="{2}">Prev</a>]</div>  
                         <div class="paging_wrap lfloat">                          
                             {0}                          
                         </div>  
                         <div class="rfloat" style="padding-top:6px;">[<a href="{3}">Next</a> | <a href="{4}">Last</a>]</div>  
                     </div>  
                 </div><br>  
             </display:setProperty>  
             <display:setProperty name="paging.banner.first">  
                 <div class="paging_footer">  
                     <div class="rfloat">  
                         <div class="lfloat" style="padding-top:6px;">[First | Prev]</div>  
                         <div class="paging_wrap lfloat">  
                              {0}  
                         </div>  
                         <div class="rfloat" style="padding-top:6px;">[<a href="{3}">Next</a> | <a href="{4}">Last</a>]</div>  
                     </div>  
                 </div><br>  
             </display:setProperty>          
             <display:setProperty name="paging.banner.last">                  
                 <div class="paging_footer">  
                     <div class="rfloat">  
                         <div class="lfloat" style="padding-top:6px;">[<a href="{1}">First</a> | <a href="{2}">Prev</a>]</div>  
                         <div class="paging_wrap lfloat">                          
                             {0}  
                         </div>  
                         <div class="rfloat" style="padding-top:6px;">[Next | Last]</div>  
                     </div>  
                 </div><br>  
             </display:setProperty>  
             <display:setProperty name="paging.banner.onepage" value="" /> <!-- Because dont want to show any value if only one page...-->  
               
             <display:setProperty name="paging.banner.page.selected">  
                 <div class="lfloat">  
                     <a onclick="return false;" class="active" href="javascript:void(0);">{0}</a>  
                 </div>  
             </display:setProperty>                      
             <display:setProperty name="paging.banner.page.link">  
                 <div class="lfloat">  
                     <a href="{1}" title="Goto page {0}">{0}</a>  
                 </div>  
             </display:setProperty>  
               
             <display:setProperty name="paging.banner.page.separator" value=" " />    <!-- Seperator between page numbers ,, i.e this will show "[First | Prev] 1 2 3 [Last | Next]"-->          
             <% MyObject myObject = (MyObject)pageContext.getAttribute("myObject"); %> <!-- Get the object from pageContext, which is writter in 'id' attribute -->  
              <display:column title="My title" class="first">  
              <!-- An y HTMl or jsp scriptlet can be used here... -->  
              </display:column>  
              <display:column property="name" title="2nd Column"/>  
              <display:column title="3rd Column"><%= myObject.getSomeValue() %></display:column>  
              ...               
         </display:table>  

4. The displaytag table can be used as follows. Where,

- pagesize is total records per page

- sort="external" means list given is sorted

- size defined the total records for which paging will be done

- name defines the list object for which the table will be generated

- id means internal object for each row which can be used in JSP scriptlets to do some data manipulations.

 <display:table name="lstObject" defaultsort="1" pagesize="20" sort="external" partialList="true"   
     size="totalCount" uid="lstObject" id="myObject"  
             export="false" requestURI="<%=someUrl%>" class="data">  
             ...  
             </display:table>  

5. You can set any property for display tag as below. You can also write HTML inside the property tag. For detailed understanding for each property this library supports, check the link - http://displaytag.sourceforge.net/1.2/configuration.html

 <display:setProperty name="paging.banner.page.separator" value=" " />

Wednesday, June 9, 2010

Liefray: Using JSONObject for Ajax in Plugin Portlet...

Many times we face situations when we need to use Ajax call from JSP pages. Using jQuery, its very easy to call any JSP through AJAX. You can just call the JSP and show its response from callback into some DOM element.

 $.ajax({  
      type: 'POST',  
      url: getUrl(),  
      data: {},                                   
      success: function(returnData) {  
          $('#someElementId').html(returnData);  
      }  
     });  

But this is useful when you want some big data OR some complex UI layout which is hard to generate using callback javascript function. Simple we call the JSP in which we have already designed the layout properly so we don't need to bother about manipulating the returnData in javascript.

Now think if you only need some small amount of data from server side, how will go? Making a new JSP for such a small task is not worhty i think. One technology is there for our help,JSON. JSON is a simple string notation of any object, which represents key-value pair like hashmap but uses its own structure to define objects.

Liferay provides com.liferay.portal.struts.JSONAction class which is a struts Action class. But to use this one in portlet we need to configure the portlet as a com.liferay.portlet. But there is one more way to use JSON with plugin portlet, using overriding serveResource method from GenericPortlet class into your portlet class.

 protected void getSomeDataAsJson(ResourceRequest request, ResourceResponse response)  
 throws PortletException, IOException {  
     String myParam = ParamUtil.getString(request, "myParam","");  
     // Some service call using params from request...  
     Obj obj = getDataFromSomeService(myParam);  
     JSONObject jsonObj = JSONFactoryUtil.createJSONObject();  
     // obj can be anything... Integer,Boolean,String or some custom POJO...  
     jsonObj.put("testData", obj);  
     OutputStream os = response.getPortletOutputStream();  
     try {  
         os.write(jsonObj.toString().getBytes());  
     }  
     finally {  
         os.close();  
     }  
 }  
 @Override  
 public void serveResource(ResourceRequest request, ResourceResponse response)  
         throws PortletException, IOException {  
     String cmd = ParamUtil.getString(request,Constants.CMD);  
     if ("getSomeDataAsJson".equals(cmd)) {  
         getSomeDataAsJson(request, response);  
     }  
 }  

The above method will provide the JSON object as a result in javascript callback function. Check the Ajax call,

 $("input:button[@name='<portlet:namespace />SomeThing']").click (function() {  
     $('#<portlet:namespace />myDiv').text("");  
     //URL which goes to your portlet...  
     var url = "<portlet:resourceURL><portlet:param name='<%=Constants.CMD %>' value='getSomeDataAsJson' /></portlet:resourceURL>";      
     //Append your hidden input fields in the resourceURL...   
     url +="&"+$('input:hidden').serialize();   
     $.ajax({  
             url: url,  
             data: {},  
             dataType: 'json',  
             success: function(message) {  
                     $('#<portlet:namespace />myDiv').text(message.testData);  
                     }  
             }  
         );      
     });  

This way we don't need to create JSPs for small data fetching. Show other ways also using simple AJAX calling (Like DWR supports, direct calling JAVA class method from JS and returns data in JS callback).

Friday, June 4, 2010

Javascript-ajax RSS feed reader - using jQuery with jGFeed ...

Check the new version of Ajax feed reader, which is using jQuery with jGFeed.

 <html><head>  
 <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>  
 <script type= "text/javascript" language='javascript'>  
 //<![CDATA[  
 (function($) {  
   $.extend( {  
 jGFeed : function(url, fnk, num, key) {  
       // Make sure url to get is defined  
       if (url == null) return false;  
       // Build Google Feed API URL  
       var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q="+url;  
       if (num != null) gurl += "&num="+num;  
       if (key != null) gurl += "&key="+key;  
       // AJAX request the API  
       $.getJSON(gurl, function(data) {  
         if (typeof fnk == 'function')  
           fnk.call(this, data.responseData.feed);  
         else  
           return false;  
       });  
     }  
   });  
 })(jQuery);  
 var strArr = ['http://www.thinkdigit.com/forum/external.php?type=RSS','http://www.snapfiles.com/feeds/sf20fw.xml',  
        'http://www.download.com/3410-2001-0-10.xml','http://www.download.com/3412-2001-0-10.xml',  
        'http://www.download.com/3412-2003-0-25.xml','http://www.videohelp.com/rss/tools',  
        'http://www.videohelp.com/rss/forum','http://www.pcstats.com/rss/rss.xml','http://feeds.feedburner.com/Techdudes',  
        'http://feeds.feedburner.com/jQueryHowto'];  
 var isXml = true;  
 function loadXml() {  
   var index = Math.floor(Math.random()*strArr.length);  
   getJsonData(strArr[index],'targetDiv');  
 }  
 //loadXml();  
 function getJsonData(dataSource, divId) {  
   $.jGFeed(dataSource,  
   function(feeds) {  
     if (!feeds) {  
       alert('there was an error');  
     }  
     var html = "";  
     for (var i=0;i<feeds.entries.length;i++) {  
       var entry = feeds.entries[i];  
       var title = entry.title;  
       var link = entry.link;  
       var description = entry.contentSnippet;  
       var pubDate = entry.publishedDate;  
       html += "<div class='entry'><h4 class='postTitle'><a class='fancy block' href='" + link + "' target='_blank'>" + title + "</a></h4>";  
       // html += "<em class='date'>" + pubDate + "</em>";  
       var categories = " Lables : ";  
       if (entry.categories && entry.categories.length>0) {  
         categories += entry.categories[0];  
         for (var j=1;j<entry.categories.length;j++) {  
           categories +=", " +entry.categories[j];  
         }  
         html += "<p><b>"+categories+"</b></p>";  
       }  
       html += "<p class='description'>" + description + "</p></div>";  
     }  
     var btn = "<input type='button' value='Reload' onclick='getJsonData(\""+dataSource +"\",\""+divId+"\");' /></br>";  
     $('#'+divId).html(btn + html);  
   },  
   50);  
 }  
 function cleartDiv(divId) {  
   var obj = document.getElementById(divId);  
   if (obj) {  
     //obj.style.display = 'none';  
     obj.innerHTML="";  
   }  
 }  
 function getNewData(url,divId) {  
   if (url!=0) {  
     if (!url) {  
       var index = Math.floor(Math.random()*strArr.length);  
       getJsonData(strArr[index],divId);  
     } else {  
       getJsonData(url,divId);  
     }  
   }  
 }  
 //window.setInterval("getNewData()", 7000); // update the data every 20 mins  
 //]]>  
 </script>  
 </head>  
 <body onload="getNewData('http://www.videohelp.com/rss/tools','targetDiv');">  
     <select onchange="javascript:getNewData(this.options[this.selectedIndex].value,'targetDiv');" size="9" style="width:25%;">  
         <option value='0' selected="selected">Please Select</option>  
         <option value='http://www.thinkdigit.com/forum/external.php?type=RSS'>ThinkDigit.com</option>  
         <option value='http://www.snapfiles.com/feeds/sf20fw.xml'>SnapFiles.com</option>  
         <option value='http://www.articlecity.com/xml/main.xml'>ArticleCity.com</option>  
         <option value='http://www.download.com/3410-2001-0-10.xml'>Download.com populars</option>  
         <option value='http://www.download.com/3412-2001-0-10.xml'>Download.com New</option>  
         <option value='http://www.download.com/3412-2003-0-25.xml'>Download.com 25 New Titles</option>  
         <option value='http://feeds.feedburner.com/Techdudes'>TechDudes</option>  
     </select>  
     <div id="linkDiv" style="width:98%;height:25px;overflow:auto;"/>  
     <div id="targetDiv" style="border:dashed 1px;background:#fafafa;width:70%;height:450px;overflow:auto;font-family:verdana;font-size:10px;"/>  
 </body>  
 </html> 
 
jGFeed: http://plugins.jquery.com/project/jgfeed 

Wednesday, June 2, 2010

jQuery - usage of $.bind method...

jQuery is widely used javascript library which provides easy ways to do complex things. By using simple Javscript, it takes too much time to code it, but jQuery simple it down to few lines.

To check multiple Checkboxes, i have written the following code.

 <script type="text/javascript" src="html/js/jquery.js"></script>  
 <script type="text/javascript">  
 //on load, register events for checkboxes...  
 $(document).ready(  
      function() {       
           $('#chk_all').change(checkAll);            
           $('form[@name="fm"] input:checkbox[@name!="chk_all"]').each (function(index) {  
                $(this).change(selectForDelete);  
           });  
      }  
 );  
 function checkAll(){  
      var isCheck = this.checked;  
      $('form[@name="fm"] input:checkbox[@name!="chk_all"]').each(function(){  
           this.checked = isCheck;  
           $(this).trigger("change");  
      });  
 }  
 function selectForDelete(){  
      var alertIdsObj = $('form[@name="fm"] input[@name="deleteIds"]');  
      if (this.checked) {  
           if (alertIdsObj.val().indexOf(this.value)==-1) {  
                if(alertIdsObj.val()=='') {  
                     alertIdsObj.val(''+this.value);  
                } else {  
                     alertIdsObj.val(alertIdsObj.val()+","+this.value);  
                }  
           }  
      } else {  
           if (alertIdsObj.val().indexOf(this.value)>=0) {  
                alertIdsObj.val(alertIdsObj.val().replace(this.value+',',''));  
                alertIdsObj.val(alertIdsObj.val().replace(','+this.value,''));  
                alertIdsObj.val(alertIdsObj.val().replace(this.value,''));  
           }  
      }  
 }  
 //Function called for item details...  
 function viewAlertDetails(alertId) {  
           $.ajax({  
            type: 'POST',  
            url: getUrl()+"&alertId="+alertId+"&cmd=detailed-market-alerts",  
            data: {},                                           
            success: function(returnData) {  
                 $('#-mainDiv').hide();  
                 $('#-detailsDiv').html(returnData);  
                 $('#-detailsDiv').show();       
            }  
           });       
 }  
 function getUrl() {  
      var url = new String(document.location);  
      var index = url.indexOf("?");  
      if (index!=-1) {  
           url = url.substring(0,index);  
      }  
      return url;  
 }  
 //function called from second page to go back to first page with latest data...  
 //Repalces the old content with new  
 function viewAlerts() {  
      $.ajax({  
            type: 'POST',  
            url: getUrl(),  
            data: {},                                           
            success: function(returnData) {       
                var myData = $(returnData).find('#-mainDiv').html();  
                $('#-mainDiv').html(myData);  
                $('#chk_all').bind('change', checkAll);  
                $('form[@name="fm"] input:checkbox[@name!="chk_all"]').each (function(index) {            
                     $(this).bind('change',selectForDelete);            
                });  
                $('#-detailsDiv').html("");  
                $('#-detailsDiv').hide();  
                $('#-mainDiv').show();  
                return true;  
            }  
           });       
      return false;  
 }  
 </script>  

The flow is as below,
- First page shows list of data.
- By clicking particular item from the list, i hides the mainDiv and shows details of the item in detailsDiv using $.ajax.
- By clicking "Back" button from detailsDiv, i again loads the main page using $.ajax.

The problem is, when i go to second page and comes on the first page using $.ajax,i change the HTML content of mainDiv with the latest data in viewAlerts() javascript function as $('#-mainDiv').html(myData);.

If you check the script, you will notice that i have registered the event handling for checkboxes in the document,One for main checkbox and one for all other checkboxes of the list, using $(document).ready() jQuery function. Event handling works fine at first page. But when we change the html content of the div afterwards, event handler automatically removed.

So to re-enable the events on checkboxes,we need to use following code in viewAlerts() javascript function.

 $('#chk_all').bind('change', checkAll);  
 $('form[@name="fm"] input:checkbox[@name!="chk_all"]').each (function(index) {  
      $(this).bind('change',selectForDelete);            
 });  

$(jQueryDomObj).bind(eventName,function) is very useful if you want to manipulate the element contents using javascript.

Tuesday, June 1, 2010

HibernateDaoSupport with HibernateTemplate - defaultAutoCommit set false...

I am working on a web application which needs hibernate for DB integration. So i decided to use hibernate with spring. As we all know that Spring is very lightweight and supports hibernate in an easy way. Also i am used to spring JdbcDaoSupport for DB integration and StoredProcedure class for SQL Server stored procedures.

While working this time i decided to use HibernateDaoSupport. Your DAO class must extend this class to use HibernateTemplate class.

Steps to make DAO using this,

- Extend HibernateDaoSupport and also an interface if you have.
- Define your methods which provides different Database operations (CREATE, DELETE, FETCH, UPDATE, INSERT etc...)
- Define required beans as below,

 <bean id="dataSource"  
 class="org.apache.commons.dbcp.BasicDataSource">  
  <property name="driverClassName">  
   <value>com.mysql.jdbc.Driver</value>  
  </property>  
  <property name="url">  
   <value>jdbc:mysql://localhost/testdb</value>  
  </property>  
  <property name="username" value="username" />  
  <property name="password" value="passwordforit" />  
  <property name="defaultAutoCommit" value="true" />  
  <property name="defaultTransactionIsolation" value="2" />  
  <property name="maxActive" value="100" />  
  <property name="maxIdle" value="50" />  
  <property name="minIdle" value="50" />  
  <property name="maxWait" value="100" />  
  <property name="initialSize" value="20" />  
 </bean>  
 <!-- Database Property -->  
 <bean id="hibernateProperties"  
 class="org.springframework.beans.factory.config.PropertiesFactoryBean">  
  <property name="properties">  
   <props>  
    <prop key="hibernate.hbm2ddl.auto">update</prop>  
    <prop key="hibernate.dialect">  
    org.hibernate.dialect.MySQLDialect</prop>  
    <prop key="hibernate.show_sql">true</prop>  
    <prop key="hibernate.cache.provider_class">  
    net.sf.ehcache.hibernate.EhCacheProvider</prop>  
   </props>  
  </property>  
 </bean>  
 <!-- Hibernate SessionFactory -->  
 <bean id="sessionFactory"  
 class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  <property name="dataSource">  
   <ref local="dataSource" />  
  </property>  
  <property name="hibernateProperties">  
   <ref bean="hibernateProperties" />  
  </property>  
  <!-- OR mapping files. -->  
  <property name="mappingResources">  
   <list>  
    <value>myMapping.hbm.xml</value>  
   </list>  
  </property>  
 </bean>  
 <bean id="MyDAOTarget" class="com.dao.MyDAO">  
  <property name="sessionFactory">  
   <ref bean="sessionFactory" />  
  </property>  
 </bean>  

- Define transactionManager for transaction managment as below,

 <bean id="transactionManager"  
 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  <property name="dataSource">  
   <ref bean="dataSource" />  
  </property>  
 </bean>  

- Define org.springframework.transaction.interceptor.TransactionProxyFactoryBean as below, which will eventually make proxy bean on the class given in target property.

 <bean id="MyDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
   <property name="transactionManager">   
     <ref bean="transactionManager"/>  
   </property>   
   <property name="target">   
     <ref bean="MyDAOTarget"/>  
   </property>   
   <property name="transactionAttributes">  
     <props>   
       <prop key="insert*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>  
       <prop key="update*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>   
       <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>  
       <prop key="find*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED, readOnly</prop>   
     </props>   
   </property>  
 </bean>  


- Use getHibernateTemplate().get(Class entityClass,Serializable id) OR getHibernateTemplate().load(Class entityClass,Serializable id) to load particular enoty from Database.
- Use getHibernateTemplate().find(String queryString,Object value) to find entities using HQL/SQL query.
- Use getHibernateTemplate().delete(), getHibernateTemplate().deleteAll() for removing entities from Database.
- Use getHibernateTemplate().update() OR getHibernateTemplate().saveOrUpdate() for updating/inserting entity in the Database.

It seems so easy right? But no, wait! All these works fine when you have <property name="defaultAutoCommit" value="true" /> . When you change this property to false, all updates to database will not take effect. Because in that case we need to begin and commit transaction form the code.

I have tried using getHibernateTemplate() for update operations but it failed. It doesn't work with transactions. So try as per the following method.

 public void updateMyObj(MyObj myObj) {  
   Session session = getSession(true);// true means allow create new session if required.  
   Transaction trans = session.beginTransaction();  
   session.saveOrUpdate(myObj);  
   trans.commit();  
 }  

Same thing works for any update operation. This is really strange, i tried for one whole day using getHibernateTemplate() but it never worked with <property name="defaultAutoCommit" value="false" />.

Friday, May 21, 2010

Hibernate : One-to-many Parent-Child relationships...

Hibernate is quite good ORM framework. When we need one-to-many relationship in hibernate, we need to take ArrayList or Set. If the structure is kind of tree, then hibernate can perform wired if not properly tweaked.


Basically if you are having some sort of many to one relationships structure from child to parent. In hibernate all depends on mapping. Tweak your mapping, Use One-to-many relationship from parent to child using java.util.Set.


Do not use ArrayList because List is ordered, so hibernate will add extra column for that ordering only.
Also check your lazy property. If you load parent and you have set lazy="false" on its child set property (variable which is of type Set), then all of its children will be loaded from DB which can affect the performance.


Also check 'inverse' property for children. If inverse is true in child table, that means you can manage the child entity separately. Otherwise you have to do that using the parent only.

Thursday, May 20, 2010

AXIS2 web service client - without sub/proxy ...

This article is regarding how to call an web service without modifying the client each time for diff. web service OR method call. Basically we use stub/proxy classes for diff. web service method calls using Axis2, but internelly it calls using XML SOAP envelopes. So, we can direcftly convert the client to use Axis2 API classes and provide an implementation which only needs to handle the response from the call. Response will be in XML format,so we need to fetch data from XML. We can covnert XML into Pojos using Castor or JAXB libs.

You can directly use ServiceClient class to call web service, which provides call using XML only and returns XML response. For different methods of web service, you have to convert the XML response to some java POJO to use it. Only Response handling needs to be done at your end. that you can do like from XML to Map etc...

So you won't need any other stub classes to call any web service, only needs to handle response XML or converted POJO.

This is the way you don't need to modify your client every time for diff. web services. You can develop like providing a response handler to client externally. So that for every different web service you will have diff. response handler class which is implementation of you interface.

//common interface for response handlers...
//implement this for diff. web service/methods

public interface WSRespHandler{
    public Object getMeResp(Object respData);
}

//pass particular handler to client when you call some WS
public class WebServiceClient {
    public Object getResp(WSRespHandler respHandler) {
        ...
        return repHandler.getMeResp(xmlData);
    }
}

References:

http://www.developer.com/java/web/article.php/3863416/Using-Axis2-and-Java-for-Asynchronous-Web-Service-Invocation-on-the-Client-Side.htm

http://www.devdaily.com/blog/post/java/java-web-service-client-read-array-list/

Facebook integration in your web application...

This is not regarding only java, you can do this on any web application in different languages also.

Facebook is getting popular now a days. Almost every site has facebook login enabled, so that if the user has facebook account he can login using that and can use the site as a registered user. For this the user must allow the site to use his facebook user data (Friends list, profile details etc...). Facebook provides different set of APIs to do such integration with your site.
 
It basically provides different client APIs which are based on different technologies lke PHP, Java, Javascript etc.. Here i will show you how to integrate facebook only using javascript API, which is the best way to do this.
 
    1. First step is, you have to include the javascript from FB as follows.  

        <script type="text/javascript"
        src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"></script>
 
    2. You have to init the Facebook JS library with you facebook API key and provide the XDReceiver url. XDReceiver.htm is provided by facebook which is to be uploaded on you server to handle the callback to Facebook's javascript functions. It will store facebook cookies on your server so that you can access the facebook session in your site to fetch facebook data for the logged in user.    

        FB.init("myApiKey","/html/xd_receiver.htm", {
        "doNotUseCachedConnectState" : false
        ,"reloadIfSessionStateChanged" : true    //Reloads the page if user logs in OR out
        ,"ifUserConnected" : showFacebookInviteLink()    //Is user connects to FB, executes the provided JS function          
        });
 
    3. Now you need to call function which will provide the facebook login popup for user. User can login into facebook and then allows the application to use his/her data.
   

        FB.Connect.requireSession(); // This will give the popup to login
      
        // This will check if FB is initiated with application key and user logged in or not. On user session, it will executes the function.
        FB.ensureInit(function() {
            FB.Facebook.get_sessionState().waitUntilReady(
                    function() {
                        
            });
          
        });
 
    4. To logout from Facebook, you just need to call JS function FB.Connect.logout();

    Now you can access different functions of the FB JS library to acces any data it supports to use on your site/application having session initiated.I will show how to show invite friends popup dialog on your site/application. Call the below function on invite button/link click event.
   

       function inviteFacebookFriends() {      
        FB.ensureInit(function() {
            FB.Facebook.get_sessionState().waitUntilReady(
                function() { //on Connect succes
                        var fbml = "";
                        fbml = '<fb:fbml>\n'
                                + '<fb:request-form\n'
                                //Redirect back to this page                           
                                + ' action="'+document.location+'"\n'                           
                                + ' method="POST"\n'
                                + ' invite="true"\n'
                                + ' type="app test invite"\n'
                                + ' content="app test inviting...\n'                           
                                + '
                                + ' label=\'Join me!\' />"\n'
                                + '>\n'           
                                + ' <fb:multi-friend-selector\n'
                                + ' rows="2"\n'
                                + ' cols="4"\n'
                                + ' bypass="Cancel"\n'
                                + ' showborder="false"\n'   
                                + ' exclude_ids="excludeIds"\n'           
                                + ' actiontext="Use this form to invite your friends to connect to my site."/>\n'
                                + ' </fb:request-form>' + ' </fb:fbml>';
                      
                        var dialog = new FB.UI.FBMLPopupDialog("Invite Friends To This Site",fbml);                                      
                        dialog.setContentWidth(650);
                        //dialog.setContentHeight(450);
                        dialog.show();
            });
        });  
    }
     
Thats it! This will show the standard popup dialog for friends invitation. Basically this FBMl will be rendered by facebook js API.Now user can select any of his friends and send them invitation to join your site. Let me know if you have any queries OR problems, will try to help around.

Sunday, March 15, 2009

Telnet Client part 2 - using Apache net implementation...

I have shown Telnet client using socket programming which is my own logic.But Apache has already done this for us in their Net package which is freely available to download.So we can use that org.apache.commons.net.telnet.TelnetClient class for using telnet connection.

Its a very simple class.You can download its source and can figure out what they have done. Though i will show simple usage for it.
TelnetClient tc = new TelnetClient();
tc.connect("localhost", 23);
Then you can register a listener thread to get response from the telnet connection shown above. For full examples, check out java2s

Its nothing new, but a good implementation what we understood so far.
If you want totally command prompt like session for telnet, then you must wait for response from execution of the given command.Then only the next command will be sent over, as we do in DOS/Terminal.So for that we must have a logic which check the input stream and receives response.

Wednesday, December 17, 2008

Snmp4J - Java library for SNMP Communication...

We all know that if we need to use more on socket programming in java then we must use native code in c++.SNMP (Simple network Management Protocol) is used for communication with the network devices.Any network device can be queried using SNMP request.Snmp4j is the library which provides you implementation to make SNMP requests.

We can query any device (Switch,PC etc...) if it has a SNMP agent running,which will handle our SNMP request and respond with the proper data.This library made it so easy for us without looking into much details of SNMP.

In basic,SNMP is used for getting information (GET requests),but sometimes it can be used to set values in the device (SET requests).Assume that every device has a list of pre-defined variables in it,which are called OID(Object IDs).These OIDs will have a specific structure (which is called MIB file,which seems like a tree structured as in registry).

OID looks like 1.3.6.1.4.1.318.1.1.1.12.3.2.1.3.1, which has a special meaning.It has a description(name) and an associated value in it.When you query particular OID (i.e 1.3.6.1....),it will give its associated value.You can set its value also (if its allowed ;)).OIDs also have communities(Public,Private etc...) which shows permissions.Mostly public community is allowed to be viewed by SNMP requests.

See the example below how to make a SNMP request,
import org.snmp4j.*;

...
...

OctetString communityName = new OctetString("public");

String ipAddressUrl = strIpAddress+"/"+161; //161 is used for SNMP Agent...

Address targetAddress = new UdpAddress(ipAddressUrl);

TransportMapping transport = new DefaultUdpTransportMapping();

Snmp snmp = new Snmp(transport);

snmp.listen();

CommunityTarget target = new CommunityTarget();

target.setAddress(targetAddress);
target.setRetries(3);
target.setTimeout(500);

PDU pdu = new PDU();
pdu.setType(PDU.GET);

OID oid = new OID("1.3.6.1.2.1.1.");
VariableBinding vb = new VariableBinding(oid);

pdu.add(vb);
...
...

snmp.send(pdu, target);
So the last line, snmp.send(pdu, target), will return the SNMP4j Response having the value for OID we set in the PDU.This is just the example of how to get any data from OID.We can set the values using SET PDU.

Monday, July 14, 2008

Remote Method call - EJB/HTTPClient/Web Service?

This is not a new thing i am talking about,but i have used this for first time. Until now i have been used to EJB for remote method invocations. I use it for some bussiness logic which is on another distributed server. And i am not ashamed of telling that i have not used Web services :(.

This was a need in my project to call a method of another application which can be on same machine or another. First i thought i need to call a EJB and its all mess because of heavy loads for a simple method call. But when i saw the implementation, i got confused how i will cuse it! But my senior told me to check using HTTPClient from apache commons.

Its very simple to call a method on servlet using HTTPClient. Check the code below. We will just use PostMethod class for parameters to be passed and execute the request. So as per the parameters,the servlet will do its work.
PostMethod postMethod = new PostMethod("http://some.blah.com");
postMethod.setParameter("some_id", "1");
postMethod.setParameter("param1", "any data");
postMethod.setParameter("param2", "any data");
...
int status = httpClient.executeMethod(postMethod); //status will be your response...
Its so simple. But though its not a call which returns something. I mean you cna see i am just passign some information to some method to invoke some processing which is independent and i don't need its response.

Friday, April 25, 2008

Castor Xml mapping: mapping.loadMapping() gives IOException for filepath

This is very know problem i think and many of you know it but then also i am writing it here.

For convert a Value Object class directly in pre-defined XML format we use castor mapping.We give xml mapping file (as we have seen in earlier tutorial) to Mapping class object as below which will write xml string in strWriter object from Object obj.
Mapping mapping = new Mapping();
mapping.loadMapping(mappingXmlFilename);
strWriter = new StringWriter();
Marshaller marshaller = new Marshaller(strWriter);
marshaller.setMapping(mapping);
marshaller.marshal(obj);
But when i given directly the filename to loadMapping method, it gives IOException as below:
IOException : \shared\p1\p2\shared\p1\p2\lai-sup-mapping.xml
i have given absolute filepath '\\shared\p1\p2\lai-sup-mapping.xml' and then also it is generating it using relative one.So throwing IOException for file.

Then i have changed the thing and instead of giving filepath, i have made a org.xml.sax.InputSource object from the xml file and passed that xml source to loadMapping() as below:

Mapping mapping = new Mapping();
InputSourcemappingSource =
newInputSource(new FileInputStream(mappingXmlFilename));

mapping.loadMapping(mappingSource);
strWriter = new StringWriter();
Marshaller marshaller = new Marshaller(strWriter);
marshaller.setMapping(mapping);
marshaller.marshal(obj);
And its working fine.Now its generating correct XML file from the given Value object.

Monday, April 21, 2008

Java Mail API with Encoded Attachment FileNames

This is very strange problem i faces as per me. May be because different email clients have different encodings or something else, but we will get encoded filename header from some email clients like lotus, blackberry phone etc.

Message header for attachment:

Content-Transfer-Encoding: base64
Content-Type: image/jpeg
Content-Disposition:attachment;
filename="=?Windows-1252?B?SU1HMDAwMTYuanBn?="

Then i was stucked with the thing that how to decode the filename.I have the filename only in subject line.But i can not trust that because say if 3 attachments are there, then there will be 3 filenames in subject in order.But we should not depend on the subject of the email.

javax.mail.internet.MimeUtility util class which helps to decode the encoded strings in message header values as below

Method:
javax.mail.internet.MimeUtility.decodeText(strValueToBeDecoded);
But most of the encodings with java 1.3.1 are not supported. At least 1.4.1 must be used.