Tuesday, July 05, 2016

Web Service Revisiting

Nowadays, it is so easy to write web services in Java by using annotations. Recalling my old days between 2003 and 2005 to compose SOAP messages and parsing it by plain Java code, then in 2006 rescued by Axis, nothing of those can be compared by the easiness provided by JAX-WS and JAX-RS, along with JAXB. All you need to do is just annotations.

And built in JDK, you do not even need to have a web server. Endpoint.publish itself can start your web service and allow you to interact with it.

Here's a very simple example of converting one of my algorithm practice to SOAP style web service.

Java code with annotations. Endpoint in main method publish it as web service and waits for it to be invoked. This is probably the simplest way of debugging a web service if you run it in debug mode.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package string;

import java.util.Arrays;
import java.util.Objects;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;

/**
1.If last characters of two strings are same, nothing much to do. 
Ignore last characters and get count for remaining strings. So we recur for lengths m-1 and n-1.
2. Else (If last characters are not same), we consider all operations on str1, consider all 
three operations on last character of first string, recursively compute minimum cost for all three operations and take minimum of three values.

Insert: Recur for m and n-1
Remove: Recur for m-1 and n
Replace: Recur for m-1 and n-1

https://en.wikipedia.org/wiki/Levenshtein_distance

 * @author Andrew Ma
 *
 */
@WebService
public class EditDistance {
 static int min(int x, int y, int z){
  return Math.min(x,Math.min(y, z));
 }

 /**
  * bottom up dp. advancing to here after understanding the recursive algorithm
  * @param s1
  * @param s2
  * @return
  */
 @WebMethod(operationName="getEditDistance")
 public int editDistanceDP(String s1, String s2){
  Objects.requireNonNull(s1);
  Objects.requireNonNull(s2);
//  if(s1.length()==0)return s2.length();
//  if(s2.length()==0)return s1.length();
  //i,j means difference so far up to i-1 in s1 and j-1 in s2
  // so the last examined positions are last characters in both string, in dp[][], that is dp[m][n]
  int[][] dp = new int[s1.length()+1][s2.length()+1];
  for (int i=0; i<=s1.length(); i++)
        {
            for (int j=0; j<=s2.length(); j++)
            {
             if(i==0)
              dp[i][j]=j;
             else if (j==0)
              dp[i][j]=i;
             //when it runs to here , i and j would be greater than 0
             //i-1 and j-1 are real index to strings
             //0 is just for dp[][]
             else if (s1.charAt(i-1)==s2.charAt(j-1))
              dp[i][j] = dp[i-1][j-1];
             else{
              //edit operation happens on s1
              dp[i][j] = 1+min(
                dp[i][j-1],//remove:means i skip one to next
                dp[i-1][j],//insert: means i keeps same, j goes to next one
                dp[i-1][j-1]//replace: both skip one
                );
             }
            }
        }
  return dp[s1.length()][s2.length()];
 }

 public static void main(String[] args) {
  String s1 = "andrewma";
  String s2 = "andyMa";
  int[][] dp = new int[s1.length()+1][s2.length()+1];
  for(int i=0;i<dp.length;i++)
   Arrays.fill(dp[i], -1);
  System.out.println(editDistanceRecursive(s1, s2, s1.length(), s2.length()));
  System.out.println(editDistanceRecursiveDP(s1, s2, s1.length(), s2.length(),dp));
  //System.out.println(editDistanceDP(s1, s2)); 
  System.out.println(editDistanceDPWiki(s1, s2));
  Endpoint.publish("http://localhost:88/editDistance", new EditDistance());
 }

}

Usually when you deploy it to some app server such as glassfish, web interface will be generated for you for testing. With this simple method, there's no tester interface except the wsdl and xsd. You can use postman to easily compose a message according to wsdl and xsd to interact with web service just deployed.

Below is a sample SOAP message composed by hand and executed in postman. The name space and message format were parsed from wsdl and xsd being used in wsdl.


   
   
       
            abcdedfg
            abcdfg
       
   


Here is response:



   
       
            2
       
   


Developing RESTful web service has similar experience when I tried with jersey a year ago. a nice thing is you can easily use browser or curl to test the service.

No comments: