Thursday, July 10, 2014

Integrating Adobe Experience Manager(AEM) with REST services

Integrating Adobe Experience Manager(AEM) with REST services

The below document explains the approach to integrate Adobe CQ5 with REST services.



Download Integrating_CQ5_with_RESTServices.pdf


Saturday, July 5, 2014

java.io.IOException: Server returned HTTP response code: 400 - While invoking the Salesforce login url from java to get the access token

java.io.IOException: Server returned HTTP response code: 400 - While invoking the Salesforce login url from java to get the access token

I was getting the below exception while invoking the Salesforce login url to get the OAuth access_token from java.

java.io.IOException: Server returned HTTP response code: 400 for URL: https://login.salesforce.com/services/oauth2/token
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1436)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at RestCaller.execute(RestCaller.java:46)
at RestCaller.main(RestCaller.java:10)

This exception will happen normally when the values of client_id, client_security, username and password are not specified correctly while invoking the login url - https://login.salesforce.com/services/oauth2/token to get the OAuth access token.

"grant_type=password&client_id=13MVG9Y6d_xxxxxxx&client_secret=8039xxxxx&username=albinsharpxxxxx&password=Albinxxxx"

In my case, I have specified all the values properly but still it was not working, it worked after resetting the password and getting the new security token - password(password+security token)


Invoking Salesforce REST based web service from Java

Invoking Salesforce REST based web service from Java

This post will explain the approach to call the Salesfore REST based webservice through java.
I have exposed a Apex class as REST service from salesforce to fetch the account details.

@RestResource(urlMapping='/AccountDetails/*')
global with sharing class AccountDetails {

    @HttpGet
    global static Account doGet() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        System.debug('Account Id:'+accountId);
        Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE Id = :accountId];
        return result;
    }
}

The communication is of two steps
  •  getting the access_token 
  •  invoking the service endpoint by attaching the access_token to the request.
To obtain an access token, we will send an HTTP POST request to the authentication endpoint exposed by Salesforce - https://login.salesforce.com/services/oauth2/token  with the details client_id, client_secret, username and password.This values can be get from the configured Connected Apps from salesforce.





Friday, July 4, 2014

Ignoring the Host Name verification while invoking the HTTPS service through HttpsURLConnection

Ignoring the Host Name verification while invoking the HTTPS service through HttpsURLConnection

Sometimes you may receive the Host Name mismatch exception while invoking the HTTPS service from the Java client even though the valid certificate is installed to the key store.

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching <Host Name> found

The root cause of the exception is the CN name of the certificate is not matching with the host name used to connect the service.

In real scenario while the certificate is signed with third party certificate authority , the CN name will be specified as the host name of the server where the service is hosted or wildcard name will be specified e.g *.example.com to represent all sub domains in a domain. So there will not be any issue while connecting to the service.

This mismatch exception will happen most of the time communicating with self signed certificate, the certificate is signed with CN name that is not matching with the host name.

How to Fix the issue

To resolve the issue, the certificate should be signed with proper CN name or we can create a custom host name verifier to customize the host name verification functionality.

We have to return true from the custom host name verifier for the host name for which the CN name is mismatching.This will connect to the service irrespective of the host name used .

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.HttpURLConnection;

public class HTTPCaller {
static {
   javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
   new javax.net.ssl.HostnameVerifier(){
       public boolean verify(String hostname,
               javax.net.ssl.SSLSession sslSession) {
           if (hostname.equals("localhost")) {
               return true;
           }
           return false;
       }
   });
}

    public static String execute() {
        String targetURL="https://localhost/test"
        URL url;
        HttpURLConnection connection = null;
        try {
            url = new URL(targetURL);
            url = new URL(url.toString());              

            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestProperty("accept", "application/xml"); //for GET service to return xml payload

            InputStream is = connection.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            System.out.println("\n Received response" + System.currentTimeMillis());

            String line;
            StringBuffer response = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return (e.getClass().getName()+":"+e.getMessage().toString());
        }
        finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }



Wednesday, July 2, 2014

Encrypting XML Payload through XSLT in Spring WS

Encrypting XML Payload through XSLT in Spring WS

The below document explain the approach to This document will explain the approach to encrypt the critical elements of XML payload while invoking the services in Spring WS or storing the data to a database table through XSLT.



Encrypting_XML_Payload.pdf


Tuesday, July 1, 2014

Unit Testing the Velocity Templates in spring

Unit Testing the Velocity Templates in spring

It is painful to test the Velocity Template  by deploying to the server while doing frequent changes.
The unit testing  will help as to overcome this and do proper testing without deploying the project to the server.
This post will explain the approach to unit test the Velocity Templates through eclipse.

Spring velocity configurations

Create a Velocity-test.xml configuration file to configure the velocity bean - instead of creating separate configuration file we can also use the project configuration file that has the velocity bean configuration (e.g. application-context.xml)


Change the vm template path accordingly.

Create a test java class (VelocityTest.java)

import java.io.*;
import java.util.ArrayList;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.thomson.ecom.core.velocity.VelocityContextBuilder;
public class VelocityTest
{
public static void main(String[] args) throws Exception
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:velocity-test.xml");
ArrayList<Employee> employeeList=new ArrayList<Employee>();

Employee emp1=new Employee();
emp1.setContactNo("111111");
emp1.setDept("CSC");
emp1.setEmail("[email protected]");
emp1.setEmpName("Albin");
emp1.setEmpNo("1");
emp1.setLocation("Bangalore");
employeeList.add(emp1);

Employee emp2=new Employee();
emp2.setContactNo("22222");
emp2.setDept("IT");
emp2.setEmail("[email protected]");
emp2.setEmpName("Albin1");
emp2.setEmpNo("2");
emp2.setLocation("Bangalore");
employeeList.add(emp2);

Employee emp3=new Employee();
emp3.setContactNo("33333");
emp3.setDept("IT");
emp3.setEmail("[email protected]");
emp3.setEmpName("Albin2");
emp3.setEmpNo("3");
emp3.setLocation("Bangalore");
employeeList.add(emp3);

VelocityEngine engine = ctx.getBean("velocityEngine", VelocityEngine.class);
Context velocityCtx = VelocityContextBuilder.getInstance().buildContext();
velocityCtx.put("empList", employeeList);

Writer w = new FileWriter(new File("D:\\Albin\\velocity.html"));
engine.mergeTemplate("EmployeeEmailTemplate.vm", velocityCtx, w);
w.close();

System.exit(0);
}
}

Change the velocity.html file path and the vm template name accordingly.
Pass the required inputs to the velocityCtx map.
Execute the VelocityTest.java; this will generate the velocity.html file in the specified location.



Resolving cvc-elt.1: Cannot find the declaration of element 'beans' in Spring

Resolving cvc-elt.1: Cannot find the declaration of element 'beans' in Spring

I was receiving the following exception while running the Spring application in standalone mode with maven and eclipse.

Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 11 in XML document from class path resource [encrypt/encrypting-test.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'beans'.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)

Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'beans'.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)

Unfortunately, I could not able to find any issue in my bean configuration file.

<? xml version="1.0" encoding="UTF-8 ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <bean id="encryptXMLPayload" class="com.encrypt.EncryptXMLPayload">
          <property name="encryptor" ref="encryptor" /> 
          <property name="messageStylesheet" value="classpath:encrypt/encryptXMLPayload.xslt" />
     </bean>
     <bean id="encryptor" class="com.encrypt.Encryptor" init-method="init">
           <property name="keyData" value="pYOkcj4_kf-4hn-A-IkclLWDBJI-T5bd"/>
     </bean> 
 </beans>

After analysis, the issue is with version mismatch between the pom.xml(spring version configured) and the schema version  configured in the bean configuration file

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.0.RELEASE</version>
<scope>compile</scope>
</dependency>

<? xml version="1.0" encoding="UTF-8 ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">


How to Fix


The issue got resolved after changing the schema version to 3.0 in the bean configuration file as shown below

<? xml version="1.0" encoding="UTF-8 ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

The spring version configured in the pom.xml and the schema version used in the bean configuration files should be matching.