Monday, December 8, 2014

Sample Jaxrs service .....

Here is a sample Jaxrs service which you can use as a backend hosted in Tomcat server.

Package structure ...

  * musicsample
        |- bean
              |- Music
        |- JaxRsApiApplication  
        |- MusicConfig
        |- MusicRestService
        |- MusicService
        |- Server


Server.java

package org.wso2.automation.musicsample;

import org.apache.catalina.Context;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import java.io.File;
import java.io.IOException;

public class Server {

    private final static Log log = LogFactory.getLog(Server.class);

    public static void main(final String[] args) throws Exception {
        final File base = createBaseDirectory();
        log.info("Using base folder: " + base.getAbsolutePath());

        final Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        tomcat.setBaseDir( base.getAbsolutePath() );

        Context context = tomcat.addContext( "/", base.getAbsolutePath() );
        Tomcat.addServlet( context, "CXFServlet", new CXFServlet() );

        context.addServletMapping( "/rest/*", "CXFServlet" );
        context.addApplicationListener( ContextLoaderListener.class.getName() );
        context.setLoader( new WebappLoader( Thread.currentThread().getContextClassLoader() ) );

        context.addParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );
        context.addParameter( "contextConfigLocation", MusicConfig.class.getName() );

        tomcat.start();
        tomcat.getServer().await();
    }

    private static File createBaseDirectory() throws IOException {
        final File base = File.createTempFile( "tmp-", "", new File("/home/dimuthu/Desktop/JMS"));

        if( !base.delete() ) {
            throw new IOException( "Cannot (re)create base folder: " + base.getAbsolutePath()  );
        }

        if( !base.mkdir() ) {
            throw new IOException( "Cannot create base folder: " + base.getAbsolutePath()  );
        }
        return base;
    }
}


MusicService.java

package org.wso2.automation.musicsample;

import org.springframework.stereotype.Service;
import org.wso2.automation.musicsample.bean.Music;

import java.util.concurrent.ConcurrentHashMap;


@Service
public class MusicService {

    private final ConcurrentHashMap< String, Music> musicCollection = new ConcurrentHashMap< String, Music >();


    public MusicService() {
        init();
    }

    final void init() {
        System.out.println("Welcome To World Of Music .... ");
        Music music = new Music();
        music.setAlbum("Gold");
        music.setSinger("Elton John");
        musicCollection.put(music.getAlbum(), music);
    }

    public Music getByAlbum( final String albumName ) {
      
        return musicCollection.get(albumName);
    }

    public void setMusic( Music music ) {

        musicCollection.put(music.getAlbum(),music);
    }
}








MusicRestService.java

package org.wso2.automation.musicsample;

import org.wso2.automation.musicsample.bean.Music;

import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/music")
public class MusicRestService {

    @Inject
    private MusicService musicService;

    @GET
    @Path("/get")
    @Produces(MediaType.APPLICATION_JSON)
    public Music getMusicInJSON(@QueryParam("album") final String albumName) {
        /*            Music music = new Music();
       music.setAlbum("Beat It !!!");
       music.setSinger("Micheal Jackson");*/

        return musicService.getByAlbum(albumName);
        //return musicService.musicCollection.get("Dimuthu");

    }

    @POST
    @Path("/post")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createMusicInJSONPOST(Music music) {

        musicService.setMusic(music);

        String result = "Album Added : " + music;
        return Response.status(201).entity(result).build();
        //return music.getAlbum();

    }

    @PUT
    @Path("/put")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createMusicInJSONPUT(Music music) {

        musicService.setMusic(music);

        String result = "Album Added : " + music;
        return Response.status(200).entity(result).build();
        //return music;

    }
}

MusicConfig.java

package org.wso2.automation.musicsample;

import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.ws.rs.ext.RuntimeDelegate;
import java.util.Arrays;

@Configuration
public class MusicConfig {
    @Bean( destroyMethod = "shutdown" )
    public SpringBus cxf() {
        return new SpringBus();
    }

    @Bean
    public Server jaxRsServer() {
        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );
        factory.setServiceBeans( Arrays.< Object >asList(musicRestService()) );
        factory.setAddress( "/" + factory.getAddress() );
        factory.setProviders( Arrays.< Object >asList( jsonProvider() ) );
        return factory.create();
    }

    @Bean
    public org.wso2.automation.musicsample.JaxRsApiApplication jaxRsApiApplication() {
        return new JaxRsApiApplication();
    }

    @Bean
    public MusicRestService musicRestService() {
        return new MusicRestService();
    }

    @Bean
    public MusicService musicService() {
        return new MusicService();
    }

    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }
}


Music.java

package org.wso2.automation.musicsample.bean;

public class Music {

        String album;
        String singer;

        public String getAlbum() {
            return album;
        }

        public void setAlbum(String album) {
            this.album = album;
        }

        public String getSinger() {
            return singer;
        }

        public void setSinger(String singer) {
            this.singer = singer;
        }

        @Override
        public String toString() {
            return "Your Album " + album + " Of " + singer + " Was Added Successfully";
        }

    }


JaxRsApiApplication.java 

package org.wso2.automation.musicsample;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath( "api" )
public class JaxRsApiApplication extends Application {
}




Friday, November 14, 2014

Useful Git commands

Q: How can I merge a distinct pull request to my local git repo ?

A:
   You can easily merge a desired pull request using the following command. If you are doing this merge at first time you need to clone a fresh check-out of the master branch to your local machine and apply this command from the console.
 
git pull https://github.com/wso2-dev/product-esb +refs/pull/78/head

Q: How do we get the current repo location of my local git repo?

A: The below command will give the git repo location your local repo is pointing to.

git remote -v

Q: Can we change my current repo url to a remote repo url

A: Yes. You can point to another repo url as below.

git remote set-url origin https://github.com/dimuthud/carbon-platform-integration-utils.git

Q: What is the git command to clone directly from a non-master branch (eg: two branches master & release-1.9.0 how to clone from release-1.9.0 branch directly without switching to release-1.9.0 after cloning from the master) 

A: Use the following git command.

git clone -b release-1.9.0 https://github.com/wso2/product-apim.git

Maven

Q : I need to go ahead and build no matter i get build failures. Can I do that with maven build?

A: Yes. Try building like this.

mvn clean install -fn 

Q : Can I directly clone a tag of a particular git branch ?

A : Yes. Lets Imagine your tag is 4.3.0 , Following command will let you directly clone the tag instead the branch.

Syntax : git clone --branch <tag_name> <repo_url>

eg:
git clone --branch carbon-platform-integration-utils-4.3.0 https://github.com/wso2/carbon-platform-integration-utils.git



Q : To See git remote urls in more detail

A : git remote show origin



Q: Creating  a new branch

git checkout -b NewBranchName
git push origin master
git checkout master
git branch      (The pointer * represents that, In which branch you are right now.)
git push origin NewBranchName



For More Info : http://stackoverflow.com/questions/9257533/what-is-the-difference-between-origin-and-upstream-on-github

Q : 1. Getting the below error -

To https://github.com/dimuthud/identity-metadata-saml2-1.git
 ! [rejected]        HEAD -> v0.5.0 (already exists)
error: failed to push some refs to 'https://github.com/dimuthud/identity-metadata-saml2-1.git'
hint: Updates were rejected because the tag already exists in the remote.

git tag -f v0.5.0
delete remote tag on github: git push origin --delete v0.5.0
git push origin v0.5.0

2. You can not use HTTPS on centos / linux based system it gets "Received HTTP code 403 from proxy after CONNECT" error:

Try using ssh :

For Windows Open a Git Bash terminal.
Generate an SSH key ssh-keygen -t rsa from the host CentOS machine. (Give Any Password)
Run cat ~/.ssh/id_rsa.pub. 

Now Add the output to your GitHub account. To do so go to: Settings -> SSH and GPG Keys -> New SSH key
Now try git clone git clone git@xxxxx:yyyy/RepoName.git

Amend your git messages:
https://gist.github.com/nepsilon/156387acf9e1e72d48fa35c4fabef0b4

Clone a specific commit from the git

git reset --hard ${SHA_value}

Tuesday, November 11, 2014

Troubleshooting ESB maven dependency issues ....

1. If you are getting the below error when running tests ...

Problem

Exception in thread "HTTP Listener I/O dispatcher-2" java.lang.NoSuchMethodError: org.apache.http.params.HttpProtocolParams.getMalformedInputAction(Lorg/apache/http/params/HttpParams;)Ljava/nio/charset/CodingErrorAction;

Solution

This is due to missing of dependency "HTTPCORE - HttpProtocolParams ". Hence we need to search for maven dependency with contains the method  - getMalformedInputAction(..) . You will easily find that the missing dependency is httpcore version. Therefore you can add the below dependency to your pom.xml.

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.1</version>
</dependency>


2. If you want to upgrade your activeMQ server version from a lower version (eg: 5.2.0) to an advanced higher version (eg: 5.9.1) you need to add these dependencies to your root pom.xml file.

            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-all</artifactId>
                <version>${activemq.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-broker</artifactId>
                <version>${activemq.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-client</artifactId>
                <version>${activemq.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.fusesource.hawtbuf</groupId>
                <artifactId>hawtbuf</artifactId>
                <version>1.9</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.geronimo.specs</groupId>
                <artifactId>geronimo-j2ee-management_1.1_spec</artifactId>
                <version>1.0.1</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.geronimo.specs</groupId>
                <artifactId>geronimo-jms_1.1_spec</artifactId>
                <version>1.1.1</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.5</version>
            </dependency>
            <dependency>
                <!-- any library that uses commons-logging will be directed to slf4j -->
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>1.7.5</version>
            </dependency>
            <dependency>
                <!-- any library that uses slf4j will be directed to java.util.logging -->
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-jdk14</artifactId>
                <version>1.7.5</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
                <version>1.7.5</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.5</version>
            </dependency>


Important code short cuts when writing ESB tests

1. If you need to retrieve the backend service url without the service name you can get the thing done as below.

RestApiAdminClient restApiAdminClient = new RestApiAdminClient(contextUrls.getBackEndUrl(),getSessionCookie();

 2. Replacing and adding a new Proxy service:

private void addProxy() throws Exception {
        String proxy = " <proxy xmlns=\"http://ws.apache.org/ns/synapse\" name=\"StockQuoteProxyPreserveHeaderScenario1\">\n" +
                       "        <target>\n" +
                       "            <inSequence>\n" +
                       "                <property name=\"preserveProcessedHeaders\" value=\"true\"/>\n" +
                       "                <send>\n" +
                       "                    <endpoint>\n" +
                       "                        <address\n" +
                       "                                uri=\"https://localhost:8243/services/UTSecureStockQuoteProxy\"/>\n" +
                       "                    </endpoint>\n" +
                       "                </send>\n" +
                       "            </inSequence>\n" +
                       "            <outSequence>\n" +
                       "                <send/>\n" +
                       "            </outSequence>\n" +
                       "        </target>\n" +
                       "    </proxy>";
        proxy = proxy.replace("https://localhost:8243/services/UTSecureStockQuoteProxy"
                , getProxyServiceURLHttps("UTSecureStockQuoteProxy"));
        addProxyService(AXIOMUtil.stringToOM(proxy));

3. If you need to send a request and do not expect a response :

axisServiceClient.fireAndForget(putRequest, getProxyServiceURLHttp("StockQuoteProxy"), "getQuote")

4. For JMS releated scenarios only :

        OMElement synapse = esbUtils.loadResource("/artifacts/ESB/mediatorconfig/property/ConcurrentConsumers.xml");
        updateESBConfiguration(JMSEndpointManager.setConfigurations(synapse));

5. To update axis2.xml file during a test run.

private ServerConfigurationManager serverManager = new ServerConfigurationManager(context);

        serverManager.applyConfiguration(new File(TestConfigurationProvider.getResourceLocation() + File.separator + "artifacts" + File.separator + "ESB"
                                                  + File.separator + "jms" + File.separator + "transport"
                                                  + File.separator + "axis2config" + File.separator
                                                  + "activemq" + File.separator + "axis2.xml"));



6.Sending API requests :

   HttpResponse response = HttpRequestUtil.sendGetRequest(getApiInvocationURL("stockquote") + "/view/IBM", null);


7. Getting the status code of a response :

 int responseStatus = 0;

        String strXMLFilename = FrameworkPathUtil.getSystemResourceLocation() + "artifacts"
                                + File.separator + "ESB" + File.separator + "mediatorconfig" +
                                File.separator + "property" + File.separator + "GetQuoteRequest.xml";

        File input = new File(strXMLFilename);
        PostMethod post = new PostMethod(getProxyServiceURLHttp("Axis2ProxyService"));
        RequestEntity entity = new FileRequestEntity(input, "text/xml");
        post.setRequestEntity(entity);
        post.setRequestHeader("SOAPAction", "getQuote");

        HttpClient httpclient = new HttpClient();

        try {
            responseStatus = httpclient.executeMethod(post);
        } finally {
            post.releaseConnection();
        }

        assertEquals(responseStatus, 200, "Response status should be 200");

Using filter to route the request to different endpoints based on the HTTP method (eg: HTTP POST & HTTP GET methods)

<inSequence>
                <filter source="get-property('axis2', 'HTTP_METHOD')" regex="POST">
                    <then>
                        <log level="custom">
                            <property name="LOG_METHOD" expression="get-property('axis2', 'HTTP_METHOD')"/>
                        </log>
                        <send>
                            <endpoint>
                                <http method="POST" uri-template="http://localhost:8080/rest/api/music/post"/>
                            </endpoint>
                        </send>
                    </then>
                    <else>
                        <log level="custom">
                            <property name="LOG_METHOD" expression="get-property('axis2', 'HTTP_METHOD')"/>
                        </log>
                        <send>
                            <endpoint>
                                <http method="GET"
                                      uri-template="http://localhost:8080/rest/api/music/get?album=Hotel%20California"/>
                            </endpoint>
                        </send>
                    </else>
                </filter>
            </inSequence>

Monday, November 10, 2014

A Simple HTTP client to retrieve response status code for Wso2 ESB

 int responseStatus = 0;
       
        String strSoapAction = "getQuote";
        // Get file to be posted
        String strXMLFilename = FrameworkPathUtil.getSystemResourceLocation() + "artifacts" + File.separator +
                                "ESB" + File.separator + "mediatorconfig/property/MyRequest.xml";

        File input = new File(strXMLFilename);

        PostMethod post = new PostMethod(getProxyServiceURLHttp("Axis2ProxyService"));
        // Request content will be retrieved directly
        // from the input stream
        RequestEntity entity = new FileRequestEntity(input, "text/xml");
        post.setRequestEntity(entity);
         post.setRequestHeader("SOAPAction", strSoapAction);
        HttpClient httpclient = new HttpClient();

        try {
            int result = httpclient.executeMethod(post);

        } finally {
            post.releaseConnection();
        }

----
MyRequest.xml file

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.samples" xmlns:xsd="http://services.samples/xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:getQuote>
         <!--Optional:-->
         <ser:request>
            <!--Optional:-->
            <xsd:symbol>WSO2</xsd:symbol>
         </ser:request>
      </ser:getQuote>
   </soapenv:Body>
</soapenv:Envelope>


A Simple HTTPClient that you can retrieve both status code and the response payload (Lets imagine your api url is "http://yourip:8280/Transform")

   SimpleHttpClient httpClient = new SimpleHttpClient();
      
    HttpResponse httpResponse = httpClient.doPost("http://yourip:8280/Transform", null, xmlPayload, "application/xml");

    String responsePayload = httpClient.getResponsePayload(httpResponse);

A Simple HTTP-Client to retrieve JSON Array responses correctly 

Notes: Lets imagine you have created an API named "Transform" . In order to retrieve the following JSON array. 

URL url = new URL(getApiInvocationURL("Transform"));
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/xml");

        String input = " ----- Your XML Array goes array";

        OutputStream os = conn.getOutputStream();
        os.write(input.getBytes());
        os.flush();

      assertTrue(conn.getResponseCode() == HttpURLConnection.HTTP_OK,
                   "Response Code Mismatch. Expected 200 : Recived " + conn.getResponseCode());

        BufferedReader br = new BufferedReader(new InputStreamReader(
                (conn.getInputStream())));
String response = br.readLine();

        assertTrue(response.contains("{ \"StockQuotes\": { \"Stock\":"), "Response is not in JSON");
        assertTrue(response.contains("IBM"), "Response does not contain Second JSON array element");
        assertTrue(response.contains("WSO2"), "Response does not contain first JSON array element");

Friday, November 7, 2014

TAF Notes

1. automation.xml - without tenants

  <userManagement>
        <superTenant>
            <tenant domain="carbon.super" key="superTenant">
                <admin>
                    <user key="superAdmin">
                        <userName>admin</userName>
                        <password>admin</password>
                    </user>
                </admin>
                <users>
                    <user key="user1">
                        <userName>testuser11</userName>
                        <password>testuser11</password>
                    </user>
                    <user key="user2">
                        <userName>testuser21</userName>
                        <password>testuser21</password>
                    </user>
                </users>
            </tenant>
        </superTenant>
       <tenants>

       </tenants>
    </userManagement>