Monday, April 21, 2014

Spring REST template with Basic Auth, Java 8 and Spring 4.0.3

There is a little bit change of how to use Spring 4.0.3 Rest Template to call REST service with basic authentication.

Here is the standalone Java code. It is easy to convert to Spring xml style.

import java.util.HashMap;
import java.util.Map;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/*
  Required library:
     org.springframework:spring-web:4.0.3
     org.apache.httpcomponents:httpclient:4.3.3
     commons-codec:commons-codec:1.9
 */
public class AuthRestService {
private String RELATIVE_IDENTITY_URL  = "http://xxxcompute-1.amazonaws.com:8082/service/rest/v1/identity/";

public String authenticateByEmail(final String email, final String password, final String domain)  {
RestTemplate restTemplate;
Credentials credentials;

//1. Set credentials
credentials = new UsernamePasswordCredentials("test", "test");

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials( AuthScope.ANY, credentials);

         //2. Bind credentialsProvider to httpClient
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
CloseableHttpClient httpClient = httpClientBuilder.build();

HttpComponentsClientHttpRequestFactory factory = new  
                       HttpComponentsClientHttpRequestFactory(httpClient);
 
//3. create restTemplate
restTemplate = new RestTemplate();
restTemplate.setRequestFactory(factory);

//4. restTemplate execute
String url = RELATIVE_IDENTITY_URL + "domain/{domain}/email/{email}";

Map parametersMap = new HashMap();
parametersMap.put("domain", domain);
parametersMap.put("email", email);

MultiValueMap postParams = new LinkedMultiValueMap();
postParams.add("password", password);

String xml = restTemplate.postForObject(url, postParams, String.class, parametersMap);
 
return xml;
}
}

Thursday, April 5, 2012

SSH slow to login and slow for any command like ls, pwd etc

If you experience of SSH is slow to login and slow for any command like ls, pwd etc. Here is the way to fix it.  In your http://javaprovider.net server with mainIP,

cd to /etc/ssh
vi  sshd_config
#adding following line at the bottom
UserDNS no

After adding the above line, then you need to restart ssh.
/etc/init.d/sshd restart

You will see.
# init.d/sshd restart
Stopping sshd:                                           [  OK  ]
Starting sshd:                                             [  OK  ]

Java Host setup for javaprovider.net VPS

http://www.javaprovider.net provides VPS with a plan of 256MB memory, 10G disk space and 100GB bandwidth. It is $10.00 a piece.  It supports Java, Tomcat, MySQL, Hibernate, Spring etc.

Here are the steps to set it up:

Once you singup and you will get “New Hosting Account Created” email from javaproject.net.
javaproject.net preload Tomcat, Java and MySQL already.

Your email from javaproject would like this:
SolusVM control panel https://cp.whitelabelbox.com:5656/
Username: yourgivenusername
Password: yourpasswd

RootPassword:  yourpasswd
Main IP:  123.456.789.012

 
------  Set up ------
1.       Login to the Server:
You can login to MainIP using root/yourpasswd with SSH.  For window, use putty.exe or cygwin

2.       Quick Test Tomcat:
Then you can do quick test by starting tomcat:
Start tomcat:
cd to /home/tomcat/tomcat/bin
./startup.sh

Test:  with web browser such as Firefox.
http://MainIP à http:// 123.456.789.012 you will see the tomcat home page.

Stop tomcat:
./shutdown.sh

3.       Setup MySQL server.
In any directory of the server type in: mysql
  3.1   create user and set privileges
  mysql>grant all privileges on *.* to 'yourUser'@'localhost' identified by 'yourPassword' with grant option;
  mysql>grant all privileges on *.* to 'yourUser'@'%' identified by 'yourPassword' with grant option;

mysql>quit

  3.2   login with new user
  mysql –h localhost –u yourUser –p
  Enter Password: yourPassword
 
  3.3   create new database
  mysql>CREATE DATABASE yourdb;
  mysql>use yourdb;
  mysql> create table testdata (
     id int not null auto_increment primary key,
     foo varchar(25),
     bar int);

  mysql> insert into testdata values(null, 'hello', 12345);
  mysql> select * from testdata;

 +----+-------+-------+
| id | foo   | bar   |
+----+-------+-------+
|  1 | hello | 12345 |
+----+-------+-------+
1 row in set (0.00 sec)

4.       Set up Tomcat data source for database connection pool
Database source would be used by hibernate to deal with database connection.
Setting related to your war file or explored directory name, for our example yourapp.war
  4.1   Create context.xml under your META-INF
        <?xml version="1.0" encoding="UTF-8"?>

<Context>
   <Resource name="jdbc/yourDS" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="yourUser" password="yourPassword"
               driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/yourdb"/>
      
    where yourUser is the user you create at step 3.1

 4.2   Modify web.xml under WEB-INF
    Add following to web.xml
    <resource-ref>
       <description>MySQL Datasource example</description>
      <res-ref-name>jdbc/yourDS</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
   </resource-ref>
  
  4.3   Create app specific xml file yourapp.xml under /home/tomcat/tomcat/conf/Catalina/localhost
       <Context path="/tracking/">
            type="javax.sql.DataSource" username="yourUser" password="yourPassword"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/yourdb " maxActive="8" maxIdle="4"/>
      </Context>
   
    Note:
    1  The name of yourapp from yourapp.xml must be same as your war file name yourapp.war
    2. Not sure why we need this, but it is required step in order to use data source.  For me, it is required by Linux but not Win 7.

5.       Set up hibernate.cfg.xml file
    <hibernate-configuration>
        <session-factory>
           <property name="connection.datasource">java:comp/env/jdbc/yourDS</property>
  

With those settings, you can upload your app with scp in cygwin or winscp to copy your war file or directory under /home/tomcat/tomcat/webapps
 
Start Tomcat, you are ready to see your app in the web browser.  Congratulation you got it.

If you are experience slow SSH access or operation, see next post.



Tuesday, November 1, 2011

JSTL usage

Collection of JSTL:
${status.index} = 0 based index
${status.count} = 1 based index
${status.first} and ${status.last}

<c:choose>
  <c:when test="${hasResult}">
     <c:forEach var="trackGroup" items="${trackHistoryGroupList}">                                 
        <c:forEach var="track" items="${trackGroup}" varStatus="status"> 
          <c:if test="${status.first}">          
            ${track.groupId} | ${track.displayName} | ${track.startTime}
          </c:if>
          | ${track.latitude} | ${track.time}  
        </c:forEach>             
     </c:forEach>
   </c:when>
   <c:otherwise>
     No track available to view
   </c:otherwise>
</c:choose> 


<c:forEach var="i" begin="1" end="24" step="1" varStatus ="status">
<c:out value="${i}" /> 
</c:forEach>

Tuesday, February 22, 2011

Linux Port forward for debug remote application

Sometime, we need to debug production server code.

Here is approach of doing this:
1) start remote server with Debug flag, ex port 8000
2) in window local host cygwin: ssh -L 8787:localhost:8000 remoteuser@remote.myserver.com
3) start eclipse with port 8787.


ps.
-Xdebug
-Xnoagent
-Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8787
or:
SET args=%args% -Xdebug -Xnoagent -J-Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n

Monday, February 21, 2011

Binary Web Service - Hessian

Currently, most web services are XML-based due to the advantage of XML self-describing and well support. However, the bandwidth and performance may be the issues for XML based web service.

Binary Web Service, by design, attempts to solve the above issues.
Hessian (http://hessian.caucho.com/) is one of binary web service implementation. We used it and it is proved to be a good approach. Following is the simple code of showing how to use Hessian.


First we create interface with two methods, hello and hiClient
public interface Basic {
public String hello();
public MyOutputResponse hiClient(MyInputRequest input);
}


Server Side:
1. Create implementation of that interface.
public class BasicService implements Basic {
private String _greeting = "My Hello world";

public void setGreeting(String greeting) {
_greeting = greeting;
}

public String hello() {
return _greeting;
}

public MyOutputResponse hiClient(MyInputRequest input) {
System.out.println(" from client: " + input.toString());
MyOutputResponse response = new MyOutputResponse();
response.setMsg("HI there from " + input.getFirstName());
return response;
}
}

2. Standard web.xml for Hessian service
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>example.service.BasicService</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>example.interfaces.Basic</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
Where home-api refers defined interface and home-class is implementation of the interfaces.

Client Side:
public class BasicClient {
public static void main(String []args)
throws Exception
{
String url = "http://localhost/hessian_webapp/hello";

HessianProxyFactory factory = new HessianProxyFactory();
Basic basic = (Basic) factory.create(Basic.class, url);

//test first API hello
System.out.println("Hello from server: " + basic.hello());

//test second API hiClient
MyInputRequest input = new MyInputRequest();
input.setFirstName("Michael");
input.setLastName("W");
MyOutputResponse response = basic.hiClient(input);

System.out.println("hiClient from server: " + response.toString());
}
}

The url of http://localhost/hessian_webapp/hello is the servlet for the service.

HessianProxyFactory factory = new HessianProxyFactory();
Basic basic = (Basic) factory.create(Basic.class, url);

Get reference of the interface

Build/Deploy
I used maven to build Hessian web service and deployed to jboss.
Here is pom file:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>hessian_webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>hessian_webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<build>
<finalName>hessian_webapp</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>example.client.BasicClient</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>


</profiles>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>3.1.5</version>
</dependency>
</dependencies>

</project>






Build/Deploy
1. build: mvn clean package
2. deploy: copy target\hessian_webapp.war to your web server
3. start server.
4. test service with following URL: http://localhost/hessian_webapp/hello
You will get "Hessian Requires POST"
5. Run client BasicClient
In command line:
mvn -Pclient

In Eclipse:
Right click BasicClient, and Run As Java Application.



Source code: click here to download source code.

Wednesday, February 10, 2010

GWT - Use Google analytics to find bug

Google analytics provides a way to monitor the user behaviors. It enables us to monitor conversion rate overall, and/or based on browser type.

Few days ago, the Google analytics conversion chart showed that IE8 conversion rate was much less than IE6 and IE7. We doubted IE8 may have some problem for our application.

With extensive research, we found that IE8 more strict on the rule of form.attributes.name.nodeValue.
If no attribute name for the form, IE6/IE7 will ignore it, while IE8 will give exception.

One of our third party Javascript used form.attributes.name.nodeValue for tracking purpose.

The interesting thing is that it only happended if newly install IE8.
If you upgrade IE8 from IE6 or IE7, there is no such problem as IE8 will run in Compatibility mode. That was the reason the problem was skiped from our developers and QA testers.

With the fix, IE8 conversion rate goes up.