Saturday, 15 October 2016

Rest API Mock Response Example via Interceptor in Spring MVC with minimal code changes

We had a requirement to mock our rest api feeding to mobile client to be able to mock the responses, since maximum time there were issues to the integrated systems, which would cause the mobile developers to loose time.

I thought about making the least possible changes to our existing service code to return responses.

  1. Client request will add a mock header attribute to the request true/false.
  2. Create a mock Interceptor which should the maximum work for you. In case its not mock forward to designated controller and execute - in this case we will add  an   attribute to the request session , name it the probably your api method eg :- validateNumber.
  3. In your controller you will need to set another attribute as the responseString (json string of the response ) your planning to set for the mock request. (so basically your controller will check for attribute in request session set in Step 2) if exists you set the response String in session.
  4. Post Handling of request in  interceptor will use the session variable for you request api name and response string and save to local file on a common path.
  5. Case 2 :- client request for mock requests , we pick up the same file as the api name requested and display the content directly from the interceptor itself.


       
// Save file for mock response 
String fileName = (String)request.getSession().getAttribute("service");
String responseString = (String)request.getSession().getAttribute("responseString");
if(fileName!=null && responseString!=null ){
 FileUtils.writeStringToFile(new File("D://"+fileName+".txt"), responseString); 
}

// Retrieve file for mock response 
File file = new File("D://"+request.getRequestURL().substring(34)+".txt");
String string = FileUtils.readFileToString(file);
response.getWriter().write(string);


       
 

Captcha Example for Java

Requirement is to authenticate a  rest service via captha alphanumeric text image to protect against robot site crawlers.

1) Create a alphanumeric string and add it to the application session.
2) Create a service to generate an image and send it as the bytestream.
3) Validate the string and the image text and authorize the user request.


       

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import org.apache.commons.lang.RandomStringUtils;


public class Captcha {

    public static void main(String[] args) throws IOException {

          System.out.println("CAPTCHA START");
          BufferedImage image = new BufferedImage(200, 50,
          BufferedImage.TYPE_INT_RGB);
          Graphics2D graphics2D = image.createGraphics();
          Map map = new HashMap();
          Color c = new Color(0.6662f, 0.4569f, 0.3232f);
          GradientPaint gp = new GradientPaint(30, 30, c, 15, 25,Color.white, true);
          graphics2D.setPaint(gp);
          Font font=new Font("Verdana", Font.CENTER_BASELINE , 26);
          graphics2D.setFont(font);
          graphics2D.drawString( RandomStringUtils.randomAlphanumeric(7),2,20);
          graphics2D.dispose();
          File outputfile = new File("capctha.png");
          ImageIO.write(image, "jpeg", outputfile);
          System.out.println("CAPTCHA END" +outputfile.getAbsolutePath());
    }
}

       
 

Sunday, 25 September 2016

Weblogic Virtual Path Directory config for Static images etc


Using the below configuration you can basically create a content repository for your application using the feature provided by weblogic to host static content .

for example below your application context is webApp

Hence static will be hosted at IP:Port/webApp/image.jpg

<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.3/weblogic-web-app.xsd">
    <wls:weblogic-version>10.3.4</wls:weblogic-version>
    <wls:context-root>webApp</wls:context-root>
    <wls:container-descriptor>
                   <!-- virtual directory -->
         <wls:index-directory-enabled>true</wls:index-directory-enabled>
         <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes>
           
    </wls:container-descriptor>
  
     <!-- virtual directory -->
         <wls:virtual-directory-mapping>
           <wls:local-path>/deployment/static</wls:local-path>
               <wls:url-pattern>*</wls:url-pattern>
         </wls:virtual-directory-mapping>
 
</wls:weblogic-web-app>

Wednesday, 21 September 2016

Input Json Model Validation using Jackson and Gson

      

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.gson.JsonIOException;

public class JsonValidator {
 
 
 public static void main(String[] args) throws JsonIOException, IOException {
  
  ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
         Validator validator = factory.getValidator();
         ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
         List jsonObjString = new ArrayList();
         jsonObjString.add("postBox: Mumbai " );
        
         for(String attribute  : jsonObjString){
             System.out.println("Attribute :\n" + attribute);
             Address user = null;
             try {
                 user = objectMapper.readValue(attribute, Address.class);
             } catch (IOException e) {
               System.out.println("Exception caught:");
             }
             if (user != null) {
                 final Set> violations = validator.validate(user);
                 if (violations.size() > 0) {
                     System.out.println("Config contains errors:");
                     for (ConstraintViolation
u : violations){ System.out.println(" \"" + u.getPropertyPath().toString() + "\"" + " " + u.getMessage()); } } else { System.out.println("NO ERRORS " ); } } }; } } /// ADD a model class of Address to test the validation and the messages returned for the import org.hibernate.validator.constraints.NotEmpty; import com.fasterxml.jackson.annotation.JsonInclude; import com.sun.istack.internal.NotNull; /** * Author : Sanal Samuel * */ @JsonInclude(JsonInclude.Include.NON_NULL) public class Address { @NotNull @NotEmpty(message="Incorrect Data") private String postBox; @NotNull @NotEmpty(message="Incorrect Data") private String flatNumber; public String getPostBox() { return postBox; } public void setPostBox(String postBox) { this.postBox = postBox; } public String getFlatNumber() { return flatNumber; } public void setFlatNumber(String flatNumber) { this.flatNumber = flatNumber; } }

Sunday, 4 September 2016

Spring Scheduler Example

Requirement to perform some action at end of day - that would be used within the application , since this was better to map our application structure , we used spring scheduler to do this task.


 xmlns:task="http://www.springframework.org/schema/task"
 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" 
 Add the above schema definition to your parent bean. 
 Below annotation in to register you anotated class.
 
 task:annotation-driven (Please add <>)

 And Finally your method to execute with the cron parameter for execution trigger details
  
   //* "0 0 * * * *" = the top of every hour of every day.
   //* "*/10 * * * * *" = every ten seconds.
   //* "0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
   //* "0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
   //* "0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
   //* "0 0 0 25 12 ?" = every Christmas Day at midnight
 
 
   +-------------------- second (0 - 59)
   |  +----------------- minute (0 - 59)
   |  |  +-------------- hour (0 - 23)
   |  |  |  +----------- day of month (1 - 31)
   |  |  |  |  +-------- month (1 - 12)
   |  |  |  |  |  +----- day of week (0 - 6) (Sunday=0 or 7)
   |  |  |  |  |  |  +-- year [optional]
   |  |  |  |  |  |  |
   *  *  *  *  *  *  * command to be executed 
 
   @Scheduled(cron = "*/10 * * * * *")
   public void demoServiceMethod()

       

Sunday, 21 August 2016

Rest Template Spring and Injecting SSL Bean for HTTPS


Requirement is to have a common service to make rest call with a third party api . To have the configuration on  HTTPS we basically require to have certificates initialized to out SSL context , (Previous post on how to setup your ssl bean in spring context)

Register the autowired bean in your class . 

 @Autowired(required=false)
 private MySSLSocketFactory socketFactory; 
  
              
Code to make the rest call in production (HTTPS)  environment.

          
   sslContext = socketFactory.getSSLContext();
   SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
   CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
   HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
   requestFactory.setHttpClient(httpClient);
   restTemplate.setRequestFactory(requestFactory);
   HttpEntity> restRequest = new HttpEntity>(map, createHeaders("userId","userPwd")));
   ResponseEntity response= restTemplate.postForEntity(URL, restRequest , String.class );

Monday, 25 July 2016

Spring Bean for (HTTPS) SSL Connectivity - JAXWS - Spring configuration for WSDL

Below code was used to consume a rest service Used this implementation to inject a factory bean with a trustFactory into my JaxWS spring bean to autowire on startup with the required certs .

Some commands useful in this context :

Adding certificates to local JDK on windows - To be Added Later

Add single Certificate to local JDK on linux servers
keytool -import -trustcacerts -keystore /filepath/java/jre/lib/security/cacerts -storepass changeit -noprompt -alias aliasName -file /certificateFilePath/certifcate.cer

Add keystore
keytool -importkeystore -trustcacerts -keystore /filepath/java/jre/lib/security/cacerts -storepass changeit -noprompt -alias aliasName -srckeystore /keyStorePath/KeyStore.jks

Delete Certificate
keytool -delete -v -keystore /filepath/java/jre/lib/security/cacerts -alias aliasName

List All Certificates
keytool -list -v -keystore /filepath/java/jre/lib/security/cacerts > cert.txt 


Example to use spring for JAXWS via JaxWsPortProxyFactoryBean

<beans:bean id="SOAPService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <beans:property name="serviceInterface" value="${service.interface}" />
        <beans:property name="wsdlDocumentUrl" value="WEB-INF/wsdl/service.wsdl" />
        <beans:property name="namespaceUri" value="${service.namespace}" />
        <beans:property name="serviceName" value="${service.name}" />
        <beans:property name="endpointAddress" value="${service.wsdl}" />
        <beans:property name="customProperties" ref="jaxwsCustomProperties" />
        <beans:property name="lookupServiceOnStartup" value="false"/>
    </beans:bean>


    <!-- Maintaining the timeout and ssl bean to connect over https -->
    <util:map id="jaxwsCustomProperties">
        <beans:entry key="com.sun.xml.ws.request.timeout">
            <beans:value type="java.lang.Integer">${service.timeout}</beans:value>
        </beans:entry>
        <beans:entry key="com.sun.xml.ws.connect.timeout">
            <beans:value type="java.lang.Integer">${service.timeout}</beans:value>
        </beans:entry>
        <beans:entry key="com.sun.xml.ws.transport.https.client.SSLSocketFactory" value-ref="mySSLSocketFactoryBean"/>
    </util:map>



 
       

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;


public class MySSLSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory factory;
    private static final String propPath = System.getProperty("intprops.pDir");
    private static String certKey = Encryptor.decryptPass(CERT_PWD);

    public MySSLSocketFactory() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {

        char[] passphrase;
        File certFile = new File(FILEPATH);
        InputStream in = new FileInputStream(certFile);
        String key =certKey;
        passphrase = key.toCharArray();
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, passphrase);
        in.close();

        SSLContext context = getSSLContext();
        context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance("SunX509");
        kmfactory.init(ks, passphrase);
        KeyManager[] kmf = kmfactory.getKeyManagers();
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        SecureRandom random = new SecureRandom();
        context.init(kmf, new TrustManager[]{tm}, random);
        factory = context.getSocketFactory();
     }

    public static MySSLSocketFactory getDefault(){
    try {
        return new MySSLSocketFactory();

    } catch (KeyManagementException e)
    {
        System.out.println("KeyManagementException");

    } catch (KeyStoreException e)
    {
        System.out.println("KeyStoreException");

    } catch (NoSuchAlgorithmException e)

    {
        System.out.println("NoSuchAlgorithmException");

    } catch (CertificateException e)

    {
        System.out.println("CertificateException");

    } catch (IOException e)

    {
        System.out.println("IOException");

    }catch (UnrecoverableKeyException e)

    {
        System.out.println("UnrecoverableKeyException");

    }
    return null;

    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;
        private X509Certificate[] chain;
        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
           return chain;
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)  throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)  throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }

    }

    @Override
    public String[] getDefaultCipherSuites() {
        return factory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return factory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException {
        return factory.createSocket(socket, string, i, bln);
    }

    @Override
    public Socket createSocket(String string, int i) throws IOException, UnknownHostException {
        return factory.createSocket(string, i);
    }

    @Override
    public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException, UnknownHostException {
        return factory.createSocket(string, i, ia, i1);
    }

    @Override
    public Socket createSocket(InetAddress ia, int i) throws IOException {
        return factory.createSocket(ia, i);
    }

    @Override
    public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException {
        return factory.createSocket(ia, i, ia1, i1);
    }

    public static SSLContext getSSLContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException{
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    System.out.println("KEYSTORE INIT");
    File certFile = new File(FILEPATH);
    InputStream in = new FileInputStream(certFile);
    trustStore.load(in,  certKey.toCharArray());
    try{
        return SSLContexts.custom().loadKeyMaterial(trustStore, certKey.toCharArray()).build();
    } catch (UnrecoverableKeyException e) {
        throw new EXCEPTION("CONNECTION FAILED ");
    }

    }

}

Monday, 27 June 2016

MultiPage Tiff file creation from multiple file upload for multiple formats.

Tiff files are genrally used for the compact size and good quality of images.
This is an example for jpeg , the same can be used for png and tiff as well.

Below code would accept a multipart file list and merge all files to create a single multipage -tiff file.

    public File mergeTiffFiles(List<MultipartFile> fileList) {
        File file = null;
        File convertedFile = null;
        try {
            int counter = 0;
            BufferedImage image[] = new BufferedImage[fileList.size()];
            for (MultipartFile imageFile : fileList) {
                convertedFile = convert(imageFile);
                SeekableStream sstream = new FileSeekableStream(convertedFile);
                ImageDecoder decoder = ImageCodec.createImageDecoder("jpeg",
                        sstream, null);
                PlanarImage pi = new NullOpImage(
                        decoder.decodeAsRenderedImage(0), null, null,
                        OpImage.OP_IO_BOUND);
                image[counter] = pi.getAsBufferedImage();
                counter++;
                sstream.close();
            }
            TIFFEncodeParam params = new TIFFEncodeParam();
            params.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2);
            file = new File("sourcePath");
            OutputStream out = new FileOutputStream(file);
            ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out,
                    params);
            List<BufferedImage> list = new ArrayList<BufferedImage>(
                    image.length);
            for (int i = 1; i < image.length; i++) {
                list.add(image[i]);
            }
            params.setExtraImages(list.iterator());
            encoder.encode(image[0]);
            out.close();
            if (convertedFile.delete()) {
                logger.debug(convertedFile.getName() + " is deleted!");
            } else {
                logger.debug("Delete operation is failed. "
                        + convertedFile.getName());
            }

        } catch (IOException e) {
            logger.error("Exception ");

        } catch (Exception e) {
            logger.error("Exception ");

        }

        return file;

    }



Here also to convert a multipart file object to a File object


 public File convert(MultipartFile file)
         {   
             File convFile = new File("sourcePath");
             try {
                convFile.createNewFile();
                 FileOutputStream fos = new FileOutputStream(convFile);
                 fos.write(file.getBytes());
                 fos.close();
                 return convFile;
            } catch (IOException e) {
               
                e.printStackTrace();
            }
            return convFile;
           
         }

Sunday, 7 February 2016

Bar Graph Using Jasper Report

Java Class to create the  PDF using the compiled .jasper file.



import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {

   public static void main(String[] args) {
      String sourceFileName =
      "C://Users//sanal//dbs.jasper";
  
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();
      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);
      Map parameters = new HashMap();
      JRDataSource dataSource = new JREmptyDataSource();
       // Make sure the output directory exists.
      File outDir = new File("C:/jasperoutput");
      outDir.mkdirs();
      System.out.println("PDF CREATED!");
      try {
         
             JasperPrint jasperPrint = JasperFillManager.fillReport(sourceFileName,parameters, beanColDataSource);
                // Export to PDF.
              JasperExportManager.exportReportToPdfFile(jasperPrint,"C://Users//sanal//test.pdf");
         

      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}



Create a DataBean POJO with 3 attributes .
   private String subjectName;
   private Integer marks;
   private Integer percentage;

DataBeanList Method will populate the databean object based on the constructor parameters.


Below the JRXML


<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="dbs" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ba415345-304b-4c2d-8021-e84b13474b53">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <field name="subjectName" class="java.lang.String"/>
    <field name="marks" class="java.lang.Integer"/>
    <field name="percentage" class="java.lang.Integer"/>
    <title>
        <band height="20" splitType="Stretch"/>
    </title>
    <pageHeader>
        <band height="10" splitType="Stretch"/>
    </pageHeader>
    <summary>
        <band height="200" splitType="Stretch">
            <barChart>
                <chart>
                    <reportElement x="17" y="24" width="231" height="154" uuid="63cb182e-1fb6-4e72-a8c0-8f83fef71691"/>
                    <chartTitle>
                        <titleExpression><![CDATA["JR Bar Chart"]]></titleExpression>
                    </chartTitle>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <categoryDataset>
                    <categorySeries>
                        <seriesExpression><![CDATA[$F{subjectName}]]></seriesExpression>
                        <categoryExpression><![CDATA[$F{subjectName}]]></categoryExpression>
                        <valueExpression><![CDATA[$F{marks}]]></valueExpression>
                    </categorySeries>
                </categoryDataset>
                <barPlot isShowTickMarks="false">
                    <plot/>
                    <itemLabel/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </barPlot>
            </barChart>
            <xyBarChart>
                <chart>
                    <reportElement x="288" y="24" width="252" height="154" uuid="8e067d93-7652-4237-b693-eaf631f720a7"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <xyDataset>
                    <xySeries>
                        <seriesExpression><![CDATA[$F{subjectName}]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{percentage}]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{marks}]]></yValueExpression>
                    </xySeries>
                </xyDataset>
                <barPlot>
                    <plot/>
                    <itemLabel/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </barPlot>
            </xyBarChart>
        </band>
    </summary>
</jasperReport>


finally how it looks





AWS Certificate Manager - Import Certificate

How to import a certificate. Use Key Store Explorer to open the cert and export keypair in PEM format  This will save a file cert.pem. Make ...