tag:blogger.com,1999:blog-14864071639976798682024-02-08T10:07:08.761-08:00Tech digestA brain dump of some of the technical challenges that I faced and dealt with.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-1486407163997679868.post-68424593323972914242011-06-20T05:45:00.000-07:002011-06-20T05:55:38.156-07:00Eclipse is becoming increasingly annoyingAs an Android developer I find Eclipse these days is becoming very unreliable. All of a sudden all my projects would not compile. I tried doing a project-> clean and build but still the error console would not tell me what is wrong. I had not made changes to any of the files. The only message I got was "Your project has errors, please fix it before trying the build".. very helpful right. The I thought let me try using my favorite IDE for all these years Netbeans, I have not done any Android projects using this super hero so a 30 sec googling is all that took to setup the environment and I imported my projects and there it is the proper error message your "com.android.sdklib.build.ApkCreationException: Debug Certificate expired on 6/18/11 11:25 PM". Thank you netbeans you are amazing.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-83931014019948278312010-12-23T08:05:00.000-08:002011-01-12T16:15:25.930-08:00Parcelable interface in androidThe most efficient way to pass custom objects between android activities in by implementing the Parcelable interface. Two methods describeContents and writeToParcel needs to be overridden <br /><br /><code><br />public class MyParcel implements Parcelable{<br /> private String name;<br /> private List<Email> emails;<br /><br /> @Override<br /> public int describeContents() {<br /> // TODO Auto-generated method stub<br /> return 0;<br /> }<br /><br /> @Override<br /> public void writeToParcel(Parcel dest, int arg1) {<br /> dest.writeString(name);<br /><br /> Bundle bundle = new Bundle();<br /> bundle.putParcelableArrayList("emails", emails);<br /> dest.writeBundle(bundle);<br /> <br /> }<br />}<br /></code><br />In this example MyParcel class has a name and a list of emails which we would like write to a parcel so that other activities can have access to it. As you can see the basic java types have their corresponding write methods to write a user defined class or a list we first create a bundle and then write it to the parcel.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-51542460261814803002010-12-21T18:15:00.000-08:002010-12-23T07:41:08.895-08:00Exposing Spring beans as a JMX managed beanI had a few Spring service beans that I wanted to expose as a JMX bean. I was using annotation to define my Spring beans and the steps are really straight forward to expose these as a JMX managed bean using the support from spring. Spring 2.5 and 3.0 comes shipped with some easy annotations to do this. First you define the spring exporter for managed resource.<br /><code><br /> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"><br /> <property name="autodetect" value="true"></property><br /> <property name="namingStrategy" ref="namingStrategy"></property><br /> <property name="assembler" ref="assembler"></property><br /> <property name="beans"><br /> <map><br /> <entry key="bean:name=myManagedBean" value-ref="myService"/><br /> <br /> </map><br /> </property><br /> </bean><br /> <bean id="attributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/><br /> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"><br /> <property name="attributeSource" ref="attributeSource"/><br /> </bean><br /> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"><br /> <property name="attributeSource" ref="attributeSource"/><br /> </bean><br /></code><br /><br />The exporter bean needs to have lazy-init flag set to false, this flag when set does not call the init code when the bean is loaded. The attributeSource bean indicates that we are going to use annotation to expose the bean attributes. And finally the namingStrategy bean defines how the managed beans are named and accessible in the jconsole. Once these beans are defined in the spring context now we are ready to code the managed resource.<br /><code><br />@Service("myService")<br />@ManagedResource(objectName = "bean:name=myManagedBean", description = "Asample")<br />public class MyServiceImpl implements MyService {<br /><br /> private Integer myManagedAttribute;<br /><br /> @ManagedAttribute(description="The bean Attribute")<br /> public void setMyManagedAttribute(Integer val){<br /> this.myManagedAttribute=val;<br /> }<br /> @ManagedAttribute(description="The bean Attribute")<br /> public Integer getMyManagedAttribute(){<br /> return myManagedAttribute;<br /> }<br /> @ManagedOperation(description="the operation that is exposed")<br /> public void myOperation(){<br /> }<br />}<br /><br /></code><br />In the example which is a Spring service we can also make it a managed resources by adding the managedResource annotation the objectName given here should be the same that was given in the exporter bean key. Then every get or set method can be annotated with managedAttribute and other methods can be annotated with managedOperation.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-13074739826058659542010-12-21T11:17:00.000-08:002010-12-21T12:42:49.461-08:00Array Copy using GenericsIf you look at the method definition of copy in the collections framework it looks something like this. <br /><code><br />public static <T> void copy(List< ? super T > to, List <? extends T> from)<br /></code><br /><br />The ? in generics means wild card i.e. In this case any class or interface that is a super class of T for the first parameter or extends T as in the second parameter. An important concept that one should understand in this example is covariance. Arrays in java are covariance i.e. if Integer extends Number then Interger[] also extends Number[]. This is not the case when it comes to generic lists where List<Integer> is not a sub class of List<Number>. With this basic understanding lets simplify the above method definition and see what happens<br /><br /><code><br />public static <T> void copy(List<T> to, List <T> from)<br /></code><br /><br />Now let us call the method as follows.<br /><code><br />List<Object> objs = Arrays.<Object>asList("San","John",1042);<br />List<Integer> ints = Arrays.<Integer>asList(10,20);<br />TestClass.<Object>copy(objs, ints); // Call(1)<br />TestClass.<Integer>copy(objs,ints); // Call (2)<br />TestClass.<Number>copy(objs,ints); // Call (3)<br /></code><br />If the rule of covariance is applied then all three calls are not legal. as List<Integer> is not a subclass of List<Object> if you consider call (1) To make call (1) legal the declaration should be modified to<br /><code><br />public static <T> void copy(List<T> to, List <? extends T> from)<br /></code><br /><br />With this method declaration call (1) is legal but how about (2) and (3) they are still not legal as List<Object> is not a subclass of List<Integer> for the "to" parameter same concept is applicable for call (3) and because of this we end up having public static <T> void copy(List< ? super T > to, List <? extends T> from) which is the most suitable for all calls. I would recommend reading the Java Generics and Collections by Maurice Naftalin to understand more about Generics in Java.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-67663477972630547152010-12-08T11:22:00.000-08:002010-12-08T12:19:36.164-08:00Spring security LDAP authenticationI was experimenting on spring security and found that with spring 2.5 LDAP authentication was a pain. This is what I did to get around the issue.<br /><br />First my maven POM had these dependencies<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /> <dependency><br /> <groupId>org.springframework</groupId><br /> <artifactId>spring</artifactId><br /> <version>2.5.6</version><br /> </dependency><br /><br /> <dependency><br /> <groupId>org.springframework.ldap</groupId><br /> <artifactId>spring-ldap</artifactId><br /> <version>1.2.1</version><br /> </dependency><br /><br /> <dependency><br /> <groupId>org.springframework.security</groupId><br /> <artifactId>spring-security-core</artifactId><br /> <version>2.0.4</version><br /> </dependency><br /></code><br /></pre><br />Your web.xml should have the contextConfigLocation which refers to the location of the spring security config xml file, the spring web context loader and the spring security filter.<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /> <context-param><br /> <param-name>contextConfigLocation</param-name><br /> <param-value><br /> classpath:/spring/context-security.xml<br /> </param-value><br /> </context-param><br /> <!-- Spring context loader servlet and listener class need to spring managed beans--><br /> <listener><br /> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class><br /> </listener><br /><br /> <servlet><br /> <servlet-name>context</servlet-name><br /> <servlet-class>org.springframework.web.context.ContextLoaderServlet </servlet-class><br /> <load-on-startup>1</load-on-startup><br /> </servlet><br /><br /> <!--spring security filter chain --><br /><br /> <filter><br /> <filter-name>springSecurityFilterChain</filter-name><br /> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><br /> </filter><br /><br /> <filter-mapping><br /> <filter-name>springSecurityFilterChain</filter-name><br /> <url-pattern>*.html</url-pattern><br /> <dispatcher>FORWARD</dispatcher><br /> <dispatcher>REQUEST</dispatcher><br /> </filter-mapping><br /></code><br /></pre><br />The contents of context-security.xml is as follows<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /><!-- first configure the LDAP url --><br /><br /><ldap-server id="appLdapServer" url="ldap://example.com:389/ou=San_Jose,o=ME" /><br /><br /><!-- configure the LDAP authentication provider here you can specify search filters <br /> which will start the LDAP search from a given node in the tree. you can also specify<br /> users with certain specific attributes so that only those users can have access to your application web page<br />--><br /><br /><ldap-authentication-provider server-ref="appLdapServer"<br /> user-search-filter="(cn={0})" group-role-attribute="ou=Engineering" <br /> user-search-base="ou=Software Eng"/><br /><br /></code><br /></pre><br /><br />Now the http intercept url xml elements need to be written for this we shall have a simple rule which shows pages in folder inbox if the user has been authenticated otherwise the user gets redirected to login or error page in folder auth so make sure you have only unsecure pages in the auth folder.<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /><http access-denied-page="/auth/denied.html"><br /> <intercept-url<br /> pattern="/**/*.xhtml"<br /> access="ROLE_NONE_GETS_ACCESS" /><br /> <intercept-url<br /> pattern="/auth/*"<br /> access="ROLE_ANONYMOUS" /><br /> <intercept-url<br /> pattern="/inbox/*"<br /> access="IS_AUTHENTICATED_FULLY" /><br /> <intercept-url<br /> pattern="/**"<br /> access="IS_AUTHENTICATED_FULLY" /><br /> <form-login<br /> login-processing-url="/j_spring_security_check.html"<br /> login-page="/auth/login.html"<br /> default-target-url="/inbox/index.html"<br /> authentication-failure-url="/auth/login.html" /><br /> <logout logout-url="/auth/logout.html"<br /> logout-success-url="/" /><br /> <anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/><br /> </http><br /></code><br /></pre><br /><br />The IS_AUTHENTICATED_FULLY is a spring security access constant which does the trick to all pages inside inbox to be visible if the LDAP authentication is successfulsanthosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-42143698343085346152009-12-29T14:23:00.000-08:002009-12-30T23:38:15.713-08:00Credit card validator in JSFIf you have a JSF page with credit card information you might want to validate the credit card number the user is entering. Different credit card companies (VISA,Master & Amex) have credit card numbers that follow different validation rules. All major credit cards will satisfy a Cyclic Redundancy Check (CRC) called Luhn Algorithm.<br /><br />Luhn Algorithm<br /><br />Step1: Sum all odd digits of the credit card number<br />Step2: Take each even digit multiply it by 2 if the result is greater than 9 subtract 9 from it then add it to the Sum of Step1<br />Step3: If sum is divisible by 10 then CRC passed else failed<br /><br />To implement this lets do the following<br />1.In your JSP page which has the credit card form add the validator to the the card number input text field<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /> <span style="color: rgb(51, 102, 255);"><h:inputText label="Credit Card Number:"</span><br /><span style="color: rgb(51, 102, 255);"> id="inpCCnumber" required="true"</span><br /><span style="color: rgb(51, 102, 255);"> value="#{backing_ccbean.cardNumber}"></span><br /><span style="color: rgb(51, 102, 255);"> <f:validator validatorId="CreditCardValidator"/></span><br /><span style="color: rgb(51, 102, 255);"> </h:inputText></span><br /><br /></code><br /></pre><br /><br />As you can see the custom credit card validator is called CreditCardValidator. The value is stored in the backing_ccbean. Assume there is a drop down list from which the user selects the card type(Visa,Master or Amex) and this value is stored in the same backing bean backing_ccbean in the attribute cardType, however this value will be set to the model object only after the validation phase so we need to directly bind to the component<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /><br /> <span style="color: rgb(51, 102, 255);"><h:selectOneListBox label="Credit card type" value="#{backing_ccbean.cardType}"</span><br /><span style="color: rgb(51, 102, 255);"> binding="#{backing_requestscope.cardTypeChoice}"> </span><br /><span style="color: rgb(51, 102, 255);"> <f:selectItem itemValue="1" itemLabel="Visa" /> </span><br /><span style="color: rgb(51, 102, 255);"> <f:selectItem itemValue="2" itemLabel="Master Card" /></span><br /><span style="color: rgb(51, 102, 255);"> <f:selectItem itemValue="3" itemLabel="American Express" /></span><br /><span style="color: rgb(51, 102, 255);"> </h:selectOneListBox> </span><br /><br /></code><br /></pre><br /><br />backing_requestscope.cardTypeChoice maps to a javax.faces.component.html.HtmlSelectOneListBox this way we get the users selection in the validation phase of the JSF life cycle.<br /><br />2. The next step would be to define CreditCardValidator in faces-config.xml. Add the following XML element to your faces-config<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><br /><code><br /><span style="color: rgb(51, 102, 255);"> <validator></span><br /><span style="color: rgb(51, 102, 255);"> <validator-id>CreditCardValidator</validator-id></span><br /><span style="color: rgb(51, 102, 255);"> <validator-class>validators.MyCreditCardValidator</validator-class></span><br /><span style="color: rgb(51, 102, 255);"> </validator></span><br /></code><br /></pre><br />The XML element is simple there is an ID and a Class we have called it MyCreditCardValidator.<br /><br />3. Now let us write the java class MyCreditCardValidator in the package validators<br /><br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /><br />package validators;<br /><br />public class MyCreditCardValidator implements javax.faces.validator.Validator{<br /><br /><br /> public void validate(FacesContext ctx,UIComponent component,Object value) throws ValidatorException{<br /> String ccnum=(String)value;<br /> // get the card type form the binding object instead of the model object<br /> HtmlSelectOneListBox cardChoiceComp= (HtmlSelectOneListBox) context.getApplication().createValueBinding("#{backing_requestscope.cardTypeChoice}").getValue(context);<br /> int cardType = ((Integer)cardChoiceComp.getValue()).intValue();<br /><br /> boolean validCard = validateCard(ccnum,cardType);<br /><br /> if (validCard==false) throw new ValidatorException(new FacesMessage(" Invalid credit card format!!!!"));<br /><br /> }<br /><br /> private boolean validateCard(String ccnum,int cardType){<br /> // visa cards always start with 4 and are either 13 or 16 digits in length<br /> final int VISA=1;<br /> // master cards are 16 digits in length and the first 2 digits range from 51 to 55<br /> final int MASTER=2;<br />// Amex cards are 15 digits in length and the first 2 digits range from 34 to 37<br /> final int AMEX=3;<br /> switch(type) {<br /> case VISA:<br /> if ((ccnum.length() != 13 && ccnum.length() != 16) ||<br /> Integer.parseInt(ccnum.substring(0,1))!=4)<br /> return false;<br /> break;<br /> case MASTER:<br /> if (ccnum.length() != 16 ||<br /> Integer.parseInt(ccnum.substring(0,2)) <> 55)<br /> return false;<br /> break;<br /> case AMEX:<br /> if (ccnum.length() != 15 ||<br /> (Integer.parseInt(ccnum.substring(0,2)) != 34 &&<br /> Integer.parseInt(ccnum.substring(0,2))) != 37))<br /> return false;<br /> break;<br /> }<br /><br /> // luhn validate<br /> char[] charArr = ccnum.toCharArray();<br /> int[] num = new int[charArr.length];<br /> int total =0;<br /> for(int i=0;i<chararr.length;i++) each="" digit="" is="" storedin="" num="" boolean="" alternate="false;" int="" i="num.length-1;"> -1; i--){<br /> if (alternate){ // multiply each even digit by 2 then add it to total<br /> num[i] *=2;<br /> if (num[i] > 9) num[i] -=9;<br /> }<br /> total +=num[i];<br /> alternate = !alternate;<br /><br /> } <br /> if (total % 10 != 0) return false;<br /><br /> return true;<br /><br /> }<br /><br /><br />}<br /><br /></chararr.length;i++)></code><br /></pre><br /><br /><br />In the MyCreditCardValidator class the most important thing to notice is how the value of card type is got since the validate method is called in the validation phase of a JSF life cycle the model objects are not set with the value hence the only way to get the value of a component other than the component that is being validated is thru the component binding.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-64863674884224304252009-12-22T13:20:00.000-08:002009-12-23T10:29:15.718-08:00Rollback JMS transactions in MDB Vs MDPIf you are writing an application which has a message driven bean or a message driven POJO you might want to put back the message in JMS destination if there is an exception in your application logic. In other words rollback the JMS transaction if there is an exception in onMessage. On a side note the acknowledgement mode of the message is considered to be AUTO_ACKNOWLEDGE instead of CLIENT_ACKNOWLEDGE as in the AUTO mode the messages are automatically removed from the queue unless a rollback is issue. Let us discuss how to issue a rollback in the case of an MDB first and then in a MDP.<br /><br /><span style="font-weight: bold;">Issuing a rollback in a Message Driven Bean (MDB)</span><br /><br />A sample MDB implements MessageDrivenBean and MessageListener as follows<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /><br />public class ExampleMDB implements javax.ejb.MessageDrivenBean, javax.jms.MessageListener{<br /><br />javax.ejb.MessageDrivenContext context;<br /><br /> public void setMessageDrivenContext(javax.ejb.MessageDrivenContext aContext) {<br /> context = aContext;<br /> }<br />// ejbCreate and ejbRemove methods go hear.<br /><br />// onMessage needs to be implemented here<br />public void onMessage(javax.jms.Message inMessage) {<br /><br /> // do your business logic here<br /> // if error in business logic rollback by calling<br /> context.setRollbackOnly();<br /><br /><br />}<br /><br />}<br /></code><br /></pre><br /><br />The message driven context is set by the container in a container managed bean. The rollback is achieved by calling the context.setRollbackOnly() when this happens the message is put back in the queue. One should be carefull as the onMessage will be called repeatedly until the processing is fine and the rollback is not issued.<br /><br /><span style="font-weight: bold;">Issuing a rollback in a Message Driven POJO (MDP)</span><br /><br />In a Spring MDP the task of issuing a rollback is as straightforward as just throwing a RunTimeException.<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /><br />public class ExampleMDP implements javax.jms.MessageListener{<br /><br /><br />public void onMessage(Message message) throws RuntimeException{<br /><br /> // if error in business logic throw a RuntimeException<br />}<br />}<br /><br /></code><br /></pre><br /><br />When the MDP is configured in the application context xml file make sure it is sessionTransacted, by setting it's value to true. Refer to my earlier article<br /><a href="http://santhoshjohn78.blogspot.com/2009/12/how-to-write-message-driven-pojo-mdp.html">how-to-write-message-driven-pojo<br /></a>santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-91006722242546502832009-12-21T14:16:00.000-08:002009-12-21T14:36:38.265-08:00IllegalStateException in Spring's JmsTemplateI have been using Spring's JmsTemplate to send messages to Queue's and Topic's in SUN Java Message Broker. The code to implement this was really simple you just configure a bean in your context called jmsTemplate with points to class org.springframework.jms.core.JmsTemplate, autowire this bean in your code and there you have all the methods to send all kinds of objects to your JMS destination.<br /><br />Every thing worked fine, but now and then the jmsTemplate.convertAndSend method used to throw an <span style="font-weight: bold;">org.springframework.jms.IllegalStateException: Session closed; nested exception is javax.jms.IllegalStateException: Session closed.</span> Now I am not sure if this is very specific to my version of JMS broker, but some more reading in the spring forum showed that it happens in other JMS brokers aswell. There seems to be a bug with the JmsTemplate spring code especially when it is multithreaded. It seems that the JMS session is shared across multiple threads and at times one thread gets hold of a closed JMS session.<br /><br />I had to find a way around this issue till the bug is fixed by handling the exception and using a custom boilerplate code for sending JMS messages,which I agree sucks big time.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-52366374567208466262009-12-17T11:12:00.000-08:002009-12-17T11:56:15.623-08:00How to write a message driven pojo (MDP)MDP is very simple to write in spring. There are quite a few examples out there. Follow these simple steps<br /><br />Step1: Write a java class which implements javax.jms.MessageListener interface and implement the onMessage method<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br />public class MyMessageListener implements javax.jms.MessageListener{<br /><br /><br /> public void onMessage(Message message) throws RuntimeException{<br /> try{<br /> // do what you have to here<br /> }catch(Throwable ex) {<br /> throw new RuntimeException(ex);<br /> }<br /> }<br />}<br /></code><br /></pre><br /><br />Step2: Add the bean to your spring context. <br />In your spring context XML file that you have defined add the following entry. if you are using anotation then this is optional<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /><bean id="myListener" class="MyMessageListener"/><br /></code><br /></pre><br /><br />Step3: Add a jms connection factory<br />Connection factories can been directly defined in the spring context in which case you need to also define the connection pooling. If your application is going to reside in an <br />application server then you can use JNDI to get the connection factory. If you are using the second approach you define the jndiTemplate then the connection factory<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /><br /><bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"/><br /><bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"><br /> <property name="jndiTemplate"><br /> <ref bean="jndiTemplate"/><br /> </property><br /> <property name="jndiName"><br /> <value>jms/QueueConnectionFactory</value><br /> </property><br /></bean><br /></code><br /></pre><br /><br />Where jms/QueueConnectionFactory is defined as a resouce in the application server along with connection pool settings.<br /><br />Step4: Add the jms container to your spring context XML file.<br />This step attaches your POJO to a specific JMS resource (Queue/Topic) <br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br /> <bean id="myJmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"><br /> <property name="connectionFactory" ref="jmsQueueConnectionFactory"/><br /> <property name="destinationName" value="MyExampleQ"/><br /> <property name="sessionTransacted" value="false"/><br /> <property name="messageListener" ref="myListener" /><br /> <property name="concurrentConsumers" value="1" /><br /> <property name="receiveTimeout" value="30000" /><br /> </bean><br /></code><br /></pre><br /><br />And there you have it a simple message driven POJO called myListener mapping to the class MyMessageListener. It listens to messages in the queue named MyExampleQ<br />this is mentioned in the property destinationName. In this example sessionTransacted is set to false which means that if an exception occurs in onMessage method<br />the message will not be rolledback i.e. the message will be removed from the queue even if onMessage method failed. In most cases you might want the message to remain<br />in the queue if your operations in onMessage failed, in which case you need to set the value to true.<br /><br />In this example concurrentConsumers is set to one you can use this property to better your performance by increasing this value.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com2tag:blogger.com,1999:blog-1486407163997679868.post-31173849602407944452009-04-21T16:56:00.000-07:002009-04-21T18:26:16.871-07:00Protecting your pages using servlet filteringAt some point in your web application development you will need to restrict access to certain pages based on login. In other words if a user goes to a protected page without logging in he/she needs to be redirected to the login page and thus enforcing security. This can be achieved using servlet filters. A servlet filter gets executed first before any JSP page is rendered and so we can check for a value of a session variable in this filter. The value is set in the login action so if a user skips login this value will not be set and so the servlet filter will throw them back to the login page. With this basic idea the implementation will be as follows.<br /><br />Step1 Create a java class which implements javax.servlet.Filter<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><code><br />class SecurityCheckFilter implements Filter {<br />{<br />private final static String FILTER_APPLIED = "_security_filter_applied";<br />private List nonRestrictedPages;<br /><br />/**<br />* This method returns true if the page is not restricted like the landing page<br />*/<br />public boolean isNonRestrictedPage(String page){<br /> Iterator it = nonRestrictedPages.iterator();<br /> boolean result = false;<br /> while (it.hasNext()) {<br /> String nonrestrictedPage = (String)it.next();<br /> if (page.endsWith(nonrestrictedPage)) {<br /> result = true;<br /> break;<br /> }<br /> }<br /> return result;<br />}<br /><br />public void init(FilterConfig conf) throws ServletException {<br /> nonRestrictedPages = new ArrayList();<br /> // index.jsp is the landing page of the application<br /> // and needs no logging in<br /> nonRestrictedPages.add("index.jsp");<br />}<br />/**<br />* This method gets called for every jsp page before the page gets rendered<br />*/<br />public void doFilter(ServletRequest request,<br /> ServletResponse response, FilterChain chain)<br /> throws IOException, ServletException {<br /> HttpServletRequest hreq = (HttpServletRequest)request;<br /> HttpServletResponse hres = (HttpServletResponse)response;<br /> HttpSession session = hreq.getSession();<br /> String requestedSession = hreq.getRequestedSessionId();<br /> String currentWebSession = hreq.getSession().getId();<br /> String currentpage = hreq.getPathTranslated();<br /><br /> // if currentpage is null or is not a jsp page don't do any filtering<br /> if (currentpage == null || !(currentpage.endsWith(".jsp")) ) {<br /> if (chain != null) chain.doFilter(request, response);<br /> return;<br /> }<br /><br /> // if the page is restricted and this filter is not<br /> // already applied do this block<br /> if ((isNonRestrictedPage(currentpage)==false) &&<br /> (request.getAttribute(FILTER_APPLIED) == null){<br /><br /> request.setAttribute(FILTER_APPLIED, Boolean.TRUE);<br /> //If the session bean is not null get the session bean property username.<br /> String user=null;<br /> // This LoggedInBean is has the login information<br /> if(((LoggedInBean)session.getAttribute("backing_loggedin_bean"))!=null) {<br /> user = ((LoggedInBean)session.getAttribute("backing_loggedin_bean")).getUserName();<br /> }<br /> // if the user is not set and the current page is not<br /> // the login page then redirect back to login page<br /> if (user==null && (!currentpage.endsWith("login.jsp")))<br /> {<br /> hres.sendRedirect("login.jsp");<br /> return;<br /> }<br /> }<br /><br /> //deliver request to next filter<br /> if (chain!=null)<br /> chain.doFilter(request, response);<br /><br />}<br />}<br /></code><br /></pre><br />Step2 Register your custom servlet filter class in the web.xml<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><br /><filter><br /> <filter-name>Security Page Filter</filter-name><br /> <filter-class>SecurityCheckFilter</filter-class><br /></filter><br /><filter-mapping><br /> <filter-name>Security Page Filter</filter-name><br /> <url-pattern>*.jsp</url-pattern><br /></filter-mapping><br /><br /></pre>santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-57531478191373088652009-02-21T13:04:00.000-08:002009-04-21T18:25:17.519-07:00Catch All exception page for a JSF web applicationIf your application wants to display a generic error page if an internal exception occurs in your web application then all you have to do is register an action listener in your faces config, under the application as follows<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br /><span style="font-style: italic; color: rgb(51, 51, 255);"><faces-config><br /><application><br /><default-render-kit-id>oracle.adf.core</default-render-kit-id><br /><action-listener><br />view.faces.GlobalActionListener<br /></action-listener><br /></application><br /><navigation-rule><br /><navigation-case><br /><from-outcome>exceptionNavigation</from-outcome><br /><to-view-id>/global_exception.html</to-view-id><br /><redirect><br /></redirect><br /></navigation-case><br /></navigation-rule><br /></faces-config></span><span style="color: rgb(51, 51, 255);"><navigation-rule><navigation-case><redirect><br /></redirect></navigation-case></navigation-rule></span><br /></pre><br />Once you have configured your faces config with the action listener you create your java class called GlobalActionListener<br /><br /><span style="font-style: italic; color: rgb(51, 51, 255);"><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />import com.sun.faces.application.ActionListenerImpl;<br />import javax.faces.application.Application;<br />import javax.faces.application.NavigationHandler;<br />import javax.faces.context.ExternalContext;<br />import javax.faces.context.FacesContext;<br />import javax.faces.event.ActionEvent;<br />import javax.faces.event.ActionListener;<br />import javax.servlet.http.HttpSession;<br /><br />public class GlobalActionListener extends ActionListenerImpl implements ActionListener{</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> public GlobalActionListener() { </span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> super();</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> }</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> public void processAction(ActionEvent event){</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> try{</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> super.processAction(event);</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> }catch(Throwable exception){</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);">//<span style="color: rgb(204, 0, 0);">This part of the code is reached if any of your pages throw an exception and if it is not handled</span></span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> FacesContext fc = FacesContext.getCurrentInstance();</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> Application app = fc.getApplication();<br /> // <span style="color: rgb(204, 0, 0);">goto this error page</span><br /></span><span style="font-style: italic; color: rgb(51, 51, 255);"> NavigationHandler nhandler = app.getNavigationHandler();</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> nhandler.handleNavigation(fc, null, "exceptionNavigation");</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> //<span style="color: rgb(204, 0, 0);"> invalidate the session</span></span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> HttpSession session = (HttpSession)ectx.getSession(false);</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> session.invalidate(); </span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> fc.renderResponse();</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> }</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);"> }</span><br /><span style="font-style: italic; color: rgb(51, 51, 255);">}</span><br /></pre><br />Our GlobalActionListener implements the interface ActionListener and implements processAction method. It also extends the default Implementation from sun's class ActionListenerImpl. All that we have to do is call the base class's process Action and if an exception is throw catch that and redirect it to an exception page. In addition to redirecting to the exception page we also invalidate the http session.<br /><br />The NavigationHandler class navigates to the exception page defined in faces config.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-72859506398656120352009-02-17T22:40:00.000-08:002009-04-21T18:31:16.956-07:00Using Client Acknowledge mode to expose a JMS topic as a Web serviceA JMS session has three acknowledge modes AUTO, CLIENT and DUPS_OK, messages are removed from the JMS destination (Queue or Topic) only when the session has acknowledged that the client has received the message. In AUTO acknowledge mode the message is acknowledged as soon as the receive method has been completed. In DUPS_OK acknowledge the message is acknowledged lazily which means the message could be sitting in the destination for some time before the broker removes it at its will. In CLIENT acknowledge mode the client after receiving the message acknowledges it by calling its acknowledge method.This mode is key when you want to expose your JMS destination as a web service.<br /><br />The one problem that needs to be solved when exposing a JMS destination as a web service is reliability. How do we make sure that the web service client has successfully received the message. In other words how do we support distributed transaction. The following example demonstrates this.<br /><br />Target is to expose a JMS topic called yahoonews as web service.<br /><br />Step1. Create a durable subscriber with CLIENT acknowledge mode<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />public Class DurableSubscriber{<br /> Context jndiContext = null;<br /> TopicConnectionFactory topicConnectionFactory = null;<br /> TopicConnection topicConnection = null;<br /> TopicSession topicSession = null;<br /> BasicTopic topic = null;<br /> TopicSubscriber topicSubscriber = null;<br /><br /> public DurableSubscriber(){<br /> try {<br /> topicConnectionFactory = new com.sun.messaging.TopicConnectionFactory();<br /> topicConnectionFactory.setProperty("imqBrokerHostName",brokerHost);<br /> topicConnectionFactory.setProperty("imqBrokerHostPort",brokerPort); <br /> <br /> topicConnection = (com.sun.messaging.jms.TopicConnection)<br /> topicConnectionFactory.createTopicConnection();<br /> topicConnection.setClientID("yahoouserid1001");<br /><br /> topicSession =<br /> topicConnection.createTopicSession(false,<br /> Session.CLIENT_ACKNOWLEDGE);<br /> topic = (com.sun.messaging.BasicTopic)topicSession.createTopic("yahoonews");<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> if (topicConnection != null) {<br /> try {<br /> topicConnection.close();<br /> } catch (javax.jms.JMSException ee) {}<br /> }<br /> }<br /> }// end constructor<br /><br /> public void startSubscriber(){<br /> try {<br /><br /> topicConnection.stop();<br /> topicSubscriber =<br /> topicSession.createDurableSubscriber(topic,<br /> "finanancialnewsSubscriber");<br /> <br /> topicConnection.start();<br /> } catch (javax.jms.JMSException e) {<br /> System.err.println("Exception occurred: " +<br /> e.toString());<br /> }<br /><br /> }<br /><br /> public javax.jms.Message getMessage(int timeout) throws Exception{<br /> <br /> javax.jms.Message m = topicSubscriber.receive(timeout);<br /> return m;<br /> }<br />}<br /></pre><br />Step2. Create a wrapper class that will exposed as web service using REST or SOAP.<br />The web service should have two functions getMessage and ackMessage.<br />The class should also store the message that needs to be acknowledged.<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />public class JMSWebService{<br /><br /> private static DurableSubscriber ds = new DurableSubscriber();<br />static{<br /> ds.startSubscriber();<br />}<br /> private javax.jms.Message ackMessage;<br /><br /> public String getMessage(){<br /> if (ackMessage==null)<br /> ackMessage = ds.getMessage(1000); // 1 sec blocking call to get messages<br /> String str = ackMessage.getText();<br /> return str;<br /> }<br /><br /> public void ackMessage(){<br /> if (ackMessage!=null)<br /> ackMessage.acknowledge();<br /> ackMessage = null;<br /> }<br />}<br /></pre><br />In this example reliability is achieved by having the ackMessage service along with getMessage, the client has to call the ackMessage function to indicate that all is well at the client side and that the client has commited the transaction at his end. If the ackMessage call is never made and the client keeps calling the getMessage function the transaction will not be commited and so the same message is returned to the client.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-42990059639389353302009-02-15T00:13:00.000-08:002009-04-21T18:28:03.182-07:00Traversing a large database result set using toplinkIf you are developing a web application at some point you would have to deal with database queries that return large result sets, your web site might not give the best user experience if it takes several minutes to display your result set with thousands of rows in it. There are several patterns that address this, if you are using plain JDBC then there is the rowid pattern to traverse large result sets. Oracle toplink makes this pattern really simple using "Scrollable Cursors", combine this with some basic pagination logic will make users traversing through thousands of records in your web application very happy.<br /><br />Here is a basic example that makes traversing an email database a breeze.<br /><br />Using workbench generate your Email class from your sample Email table, work bench will also generate the database session file which have connection pool information.<br /><br />Lets call our data access class EmailDAO<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />public class EmailDAO{<br /> private static Server dbServer;<br /><br />class EmailResultSet{<br /> String mymail;<br /> Integer totalEmails;<br /> Integer pagesize;<br /> Integer pagenumber;<br /> Vector emails;<br />};<br /><br /> static{<br /> // in 3 tier there needs to be one server instance and multiple client instances<br /> // db-session.xml contains the database connection information and should be in classpath<br /> XMLSessionConfigLoader loader = new XMLSessionConfigLoader("db-session.xml");<br /> SessionManager mgr = SessionManager.getManager();<br /> dbServer = (ServerSession)mgr.getSession(loader, "DBSession",<br /> Thread.currentThread().getContextClassLoader());<br /> }<br /><br />/*<br /> * mymail is the email address whose email we need to return<br /> * pagesize is the number of emails to be returned.<br /> * pagenumber<br /> */<br /> public EmailResultSet <email>getMails(</email>EmailResultSet emset<email>){<br /> // Step 1 Establish connection using toplink 3 tier architecture<br /> Session clientSession = establishConnection();<br /> <br /> // Step2 construct the query<br /> ExpressionBuilder exbuilder = new ExpressionBuilder();<br /> Expression whereclause= exbuilder.get("emailaddress").equal(emset.mymail);<br /> ReadAllQuery rquery = new ReadAllQuery(Email.class,whereclause);<br /> rquery.addDescendingOrdering("time"); // sort by time column<br /><br /> // Step3 tell the read query you want the result set split into chuncks of emails each chunk has <span style="font-style: italic;">pagesize</span> number of emails in them<br /> rquery.useScrollableCursor(emset.pagesize);<br /> <br /> // Step4 execute the query<br /> ScrollableCursor cursor = (ScrollableCursor) clientSession.execute(rquery);<br /> // instead of returning a ResultSet as in a conventional execute call a cursor is returned.<br /><br /> // Step 5 find total emails<br /></email> cursor.last();<br /> // find the total number of email records by going to the last records position <br /> emset.totalEmails = new Integer(cursor.getPosition());<br /><email><br /> // Step 6 position the cursor<br /> // If pagenumber is greater than zero it means the caller knows which page he wants else position it to the first page<br /> if (emset.pagenumber>0)<br /> cursor.absolute(pagenumber); //point the cursor to the wanted page<br /> else<br /></email> cursor.first();<br /><email> <br /> // Step 7 get the result set<br /> Vector results = new Vector(emset.pagesize);<br /> for (int i=0; i<</email>emset.pagesize <email>&& cursor.hasNext(); i++)<br /> {<br /> results.add(cursor.next());<br /> <br /> }<br /> emset.emails=results;<br /> return emset;<br /><br /> }<br /><br /> public Session establishConnection(){<br /> ConnectionPolicy connectionPolicy = new ConnectionPolicy();<br /> // Use an exclusive connection for the session<br /> connectionPolicy.setShouldUseExclusiveConnection(true);<br /> Session clientSession = dbServer.acquireClientSession(connectionPolicy);<br /> return clientSession;<br /><br /> }<br /><br />}<br /></email><br /></pre>santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-62924892408291887252009-02-14T16:45:00.000-08:002009-04-21T18:28:43.287-07:00JPA Entities with composite keysEJB3 spec has made a real come back with JPA. Very often when we need to create a POJO with a composite primary key. JPA makes this very simple. If you want to create an Employee POJO with a composite primary key as first name and last name this is how you do it.<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />@IDClass(EmployeePK.class)<br />@Entity(name="EMPLOYEE")<br />public class Employee implements Serializable{<br /> <br /> @ID<br /> private String firstName;<br /> @ID<br /> private String lastName;<br /> private String qualification;<br /> private String speciality;<br /> <br /> // getters and setters go here<br /><br />}<br /><br /></pre><br /><br />Now create a class called EmployeePK in the same package as Employee class with attributes firstName and lastName.<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><br />public class EmployeePK implements Serializable{<br /> private String firstName;<br /> private String lastName;<br /><br /> // getters and setters for firstName and lastName go here...<br /><br />}<br /></pre>santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0tag:blogger.com,1999:blog-1486407163997679868.post-42878378591679895042009-02-14T11:39:00.000-08:002009-02-18T09:53:59.935-08:00REST vs SOAPREST or Representational State Transfer has becoming more popular in the SOA world due to its simplicity compared to SOAP. Using SOAP it is definitely possible for different kinds of clients (java, .net etc) to call a SOAP service, but the style of the service does play a role in what the client can and cannot do. For instance .net client will have trouble calling a JAX-RPC style service. With document literal style all bean mappings in the WSDD should have name spaces which is not required in JAX-RPC. REST has made this very simple by dealing with XML or JSON instead of marshalled objects. The disadvantage being that the client will be getting back an XML or JSON.santhosh johnhttp://www.blogger.com/profile/07277141409643870082noreply@blogger.com0