Free API management choices for distributed Restful Web Service

If you are looking for cheaper solution for the web service API management, this list might can help to give some hints.

As far you have distributed or micro web service, you will involve in the how to put all the shared feature into one place for each WS, such security, authentication and auditing. Here I list some free or low cost solution for the API lifecycle management framework and products.  When you use amazon AWS or Microsoft Azure cloud, they already supply similar service. For the open source way for small companies who do not want the bundle to a cloud provider, a self-controlled API management solution will give you more flexibility and independence for future migration.

Basically they have either on-premise or as-a-service model to go. With on-premise, means be deployed in either a physical or virtual data center. And as-a-service cloud version will let you integrate with cloud based API management and you can manage it from anywhere.

  1. WSO2 on-premises – WSO2 API Manager is a 100% open source enterprise-class solution that supports API publishing, lifecycle management, application development, access control, rate limiting and analytics in one cleanly integrated system. Running on java, most database and Apache ActiveMQ. Apache 2.0 license.
  2. Kong Community Edition  – open source with a lot customers base. Kong’s server, based on the widely adopted NGINX HTTP server, which is a reverse proxy processing your clients’ requests to your upstream services. Kong’s datastore, in which the configuration is stored to allow you to horizontally scale Kong nodes. Apache Cassandra and PostgreSQL be used.
  1. Tyk On-Premises – not open source, Single gateway Tyk Pro licences are FREE forever. Simply install your preferred package FREE for a single gateway, affordable at scale. No need to maintain forks, third party dependencies, or purchase SaaS add-ons. Just download the FREE Open Source API Gateway, get a FREE Tyk dashboard licence, use Tyk commercially… for FREE. No hidden costs, no restrictions on number of users, APIs or analytics retention. The entire platform, under your control, on your own servers. Priced according to the number of gateways in your environment, not the size of your team. Full access to the entire platform, no features held-back, starts from FREE!
  2. Apiman (not add new feature any more after redhat get the 3scale) – simple to use, install on wildfly ( Elasticsearch) or tomcat 8
  3. Api Umbleralla – looks like easy to use and install – require MongoDB and Elasticsearch
  4. gravitee.io – a very new API manager, has the gateway, manange API and portal three parts,   required MongoDB to store mandatory data and ElasticSearch (Apache License V2)
  5. Apigee – acquired by google, not free.
  6. Apiary free edition – with oracle, API Blueprint is simple and accessible to everybody involved in the API lifecycle. Its syntax is concise yet expressive. API Blueprint is completely open sourced under the MIT license. Its future is transparent and open. API Blueprint doesn’t need a closed work group. Instead it uses the RFC process similar to Rust language  or Django Enhancement Proposal RFC processes.

Solve the Json/Java polymorphism request by Jackson

By W.ZH

When convert between json and jave objects, you could often face the polymorphism issue.
Such as a json of Content could be:

{
  "type":"valuea",
  "value": {
    "valueaName": "corn",
    "bar":  "sweet"
  }
}

and also could be

{
  "type":"valueb",
  "value": {
    "valuebName": "toy",
    "color":  "yellow",
    "price":  "20"     
  }
}

Value objects in fact is depends on the type data to change. This requires that depending on the type data and create different value’s object at Java side, How to do?

Here is the solution at the Jackson code by using the     @JsonTypeInfo

let us define a abstract class Value and another two class ValueA and ValueB to Extends it.

public abstract class Value {
}

and ValueA to inherit Value

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ValueA extends Value {

    @JsonProperty("valueaName")
    private String valueaName = "";

    @JsonProperty("bar")
    private String bar;
....................................
....................................
}

and ValueB Class to inherit Value.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ValueB extends Value {

    @JsonProperty("valuebName")
    private String valuebName = "";

    @JsonProperty("color")
    private String color;

    @JsonProperty("price")
    private String price;
....................................
....................................
}

 

Then after that we can create a Class for Content to let “type” files  work as a EXTERNAL_PROPERTY to control the Value object in side the Content:

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Content {

    @JsonProperty("type")
    private String type;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("value")
    private Value value = null;
    
    public Content (){
    }
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
    @JsonSubTypes({ @Type(value = ValueA.class, name = "valuea"),@Type(value = ValueB.class, name = "valueb")})
    public void setValue(Value value) {
        this.value = value;
    }

    public Value getValue() {
        return value;
    }

}

In this way. @JsonTypeInfo in fact define how to rely on “type” to dynamically  serialize and de-serialize the json/java object.

To make this properly work, your Jackson version must higher than the 2.5 version. As I have faced the duplicated fields bug in the 2.5  version Jackson , here is sample dependency:

 

        <!-- Jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.0</version>
        </dependency>

 

 

Spring MVC + Security Note (4) – Migrate from Spring Security 3.X to 4.X

By W.ZH

Refer to this link

http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-xml.html

Here are some notes that common change in page or configuration files:

  1. default URL for login and logout form action are changed:
    /j_spring_security_logout     to /logout
    /j_spring_security_check     to /login
    So we need to change our JSP content for these two.
  2. Default csrf is enabled… so if you want to be disabled, just add this
    <csrf disabled=”true”/> in the <http />tag
    If you want enable, you do not need to do sth.
  3. <access-denied-handler error-page=”/page/403″ />  put inside the <http />
    not like old on as the attribute <http *** />
  4. If you have more than one roles, you can not use the
    access=”ROLE_USER,ROLE_ADMIN”  any more, you have to change to<http auto-config=”true” use-expressions=”true” >
    …..
    <intercept-url  ……. access=”hasAnyRole(‘ROLE_USER’,’ROLE_ADMIN’)” …..you maybe have others need changes, need to refer to reference page

How to consume json object from Spring MVC controller input directly

By WZH

This is small note about the json input directly to Spring MVC controller side, jackson will auto convert it to Java object you want:

  1. Make sure has this jar added

 <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.0</version>
  </dependency>

2.  Controller side

@RequestMapping(value = urlPatternController, method = RequestMethod.POST)
public @ResponseBody Person createPerson(@RequestBody Person jsonString) {
   Person person=personService.savedata(jsonString);
   return person;
}

@RequestBody – Covert Json object to java
@ResponseBody– convert Java object to json

3. JS client side :

 

$.ajax("<%=path%>/web/urlPatternController", {
                           type:'POST',
                           dataType: 'json',
                           data: person
                    })

 

Link can be refered

 

 

A special case for de-serialize Polymorphic class by Jackson

A special case for de-serialize Polymorphic class by Jackson

 

By WZh   Apr 2015

A very good article about the de-serialize the data in Jackson from Json to JAVA is already at this article

  1. http://programmerbruce.blogspot.co.uk/2011/05/deserialize-json-with-jackson-into.html

But a special case we have met is not in that article. Input json sample:

//   {

“type”:”dog”,

//     “animal”:

//           {“name”:”Spike”,

// “breed”:”mutt”,

//            “leash_color”:”red”}

}

or

//   {

“type”:”cat”,

//     “animal”:

//           {“name”:”Fluffy”,

//           “favorite_toy”:”spider ring”}

//   }

This means type is not inside the abstract class itself, type is controlled by parent class fields and also we want to use getter and setter in the parent class for “type” in other java code, to type must be cleared defined at Zoo class as Java field.

Here is the solution after research!

class Zoo

{

private String type;

private Animal animal;  

@JsonTypeId

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

@JsonTypeInfo(

use = JsonTypeInfo.Id.NAME,

include = JsonTypeInfo.As.EXTERNAL_PROPERTY,

property = “type”)

@JsonSubTypes({     @Type(value = Cat.class, name = “cat”),  

    @Type(value = Dog.class, name = “dog”) })  

public void setAnimal ( Animal value) {

this.animal = value;

}

public Animal getAnimal () {

return animal;

}

}

abstract class Animal

{

}

class Dog extends Animal

{

  public String name;

  public String breed;

  public String leashColor;

}

class Cat extends Animal

{

  public String name;

  public String favoriteToy;

}

the most important thing in the code is :

  1. @JsonTypeId set to getter for “type” and let the jackson do not create duplicate “type” in the json
  2. @JsonTypeInfo defined with JsonTypeInfo.As.EXTERNAL_PROPERTY to let the Animal class can be controlled by the external property “type” to do the Polymorphic
  3. @JsonTypeInfo is put to the setter of the abstract class to contorl the Polymorphic

workarea SOAP header cause the SOAPFaultException

By W.ZH Dec 2014

Issue:

When I was working on a project about the WS, my client jar always get this error:

Get Eligibility failed. Severity level is 5. Msg=SOAPFaultException – FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [15
] FaultActor [null] Detail [<detail><bea_fault:stacktrace xmlns:bea_fault=”http://www.bea.com/servers/wls70/webservice/fault/1.0.0″>java.lang.ArrayIndexOutOfBoundsException: 15
at com.sun.beans.ObjectHandler.dequeueResult(ObjectHandler.java:139)
at java.beans.XMLDecoder.readObject(XMLDecoder.java:201)
at weblogic.wsee.workarea.WorkContextXmlInputAdapter.readUTF(WorkContextXmlInputAdapter.java:111)
at weblogic.workarea.spi.WorkContextEntryImpl.readEntry(WorkContextEntryImpl.java:92)
at weblogic.workarea.WorkContextLocalMap.receiveResponse(WorkContextLocalMap.java:226)
at weblogic.workarea.WorkContextMapImpl.receiveResponse(WorkContextMapImpl.java:182)
at weblogic.wsee.workarea.WorkAreaClientHandler.handleResponse(WorkAreaClientHandler.java:49)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:287)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:271)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.handleResponse(ClientDispatcher.java:213)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.dispatch(ClientDispatcher.java:150)
at weblogic.wsee.ws.WsStub.invoke(WsStub.java:87)
at weblogic.wsee.jaxrpc.StubImpl._invoke(StubImpl.java:341)

When I look at the SOAP XML. found this in the header:

<work:WorkContext xmlns:wsu=”http://schemas.xmlsoap.org/ws/2002/07/utility&#8221;

                      xmlns:work=”http://bea.com/2004/06/soap/workarea/”&gt;

     <java class=”java.beans.XMLDecoder”>

      <string>**************</string>

      <int>214</int>

      <string>weblogic.workarea.StringWorkContext</string>

      <string>1.4.1.18</string>

      <string>oracle.dms.context.internal.wls.WLSContextFamily</string>

      <int>335</int>

      <string>weblogic.workarea.SerializableWorkContext</string>

      <int>356</int>

      <array class=”byte” length=”356″>

       <void index=”0″>

       ……………………………………..

      <boolean>false</boolean>

      <string/>

     </java>

    </work:WorkContext>

 

Reason:

As my jar client is legacy code, so it in fact can not read this extra header properly, so it will get error.

Solution:

Use this flag at your setDomainEnv.sh to change java flag for this extra header:

-Dweblogic.wsee.workarea.skipWorkAreaHeader=true

after restart server. it will be fine

Some cool tips of Jackson

Some cool tips of Jackson

from Ted M. Young

  • To make the JSON easier to read, you can tell ObjectMapper to use a “pretty printer”,

ObjectMapper objectMapper = new ObjectMapper();

Book jacksonCookbook = new JacksonCookbook();

String json = objectMapper

.writerWithDefaultPrettyPrinter()

.writeValueAsString(jacksonCookbook);

System.out.println(json);

 

If you always want to pretty-print the output, you can configure the ObjectMapper instance directly using the SerializationFeature class:


ObjectMapper objectMapper = new ObjectMapper();

objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

 

The enable method here turns on the INDENT_OUTPUT feature, which tells Jackson to use the DefaultPrettyPrinter when serializing your objects. The code

objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true)

  • If you have property values in your data that can be null, but don’t want them serialized when they are, you can do the following to make the setting global for all uses of this objectMapper reference:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

If you only want to do this on a per-class basis, you can add the @JsonInclude annotation above the class or interface definition:


@JsonSerialize(include = Inclusion.NON_NULL)
public class HasNullValues {private String optionalSecondAddress; // nullable field

 

  • Sometimes you’ll want the properties that in your JSON output to be in a specific order, perhaps because you have tests or clients that rely on the ordering (I’d try to avoid that, but sometimes it’snot under your control), or you want it to be easier to find a certain property when looking at the JSON during debugging.

To order on a per-class basis, use the @JsonPropertyOrder annotation:


@JsonPropertyOrder({“id”, “symbol”})
public class Currency {public String symbol;

public String shortName;

public String longName;

public long id;

}

This will ensure that the id property will be first, followed by the symbol property, with the rest in an undetermined order.

If you wanted them simply in alphabetic order, you would use the alphabetic parameter in the annotation:

@JsonPropertyOrder(alphabetic = true)

If you always want the properties sorted alphabetically, configure the ObjectMapper instance directly:

objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);

Note that the above settings won’t affect the order of the contents of any maps that you have (e.g., a HashMap). If you want the output of maps to be ordered by their keys, you’ll need to turn on the ORDER_MAP_ENTRIES_BY_KEYS feature:

objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);

local class incompatible: stream classdesc serialVersionUID = -4312319268131871162, local class serialVersionUID = -5312119737527277188

    By W.ZH  Aug 2014

Issue:

When we use some webservice , we get error like this :

java.io.InvalidClassException: com.abc.EmailInfo; local class incompatible: stream classdesc serialVersionUID = -4312319268131871162, local class serialVersionUID = -5312119737527277188

com.abc.EmailInfo is a java object is used in some code.

 

 

Reason:

com.abc.EmailInfo exist in fact in several jar files. each jaf file in fact contain a different version of the  EmailInfo  class, even class source code could lokks like same.

 

What we should do is:

1. find out all the jar files that contain this class file:  j1.jar and j2.jar such as.

2. use serialver to check the serialVersionUID of each class in each jar:

       C:\SVN\….WEB-INF\lib>serialver -classpath jar1.jar com.abc.EmailInfo

        com.abc.EmailInfo:    static final long serialVersionUID = -5312119737527277188L;

    

       C:\SVN\….WEB-INF\lib>serialver -classpath jar2.jar com.abc.EmailInfo

        com.abc.EmailInfo:    static final long serialVersionUID = -4312319268131871162L;

3. now you see the reason of the class with same name of diff version in fact will creat different serialVersionUID

4. so try to unzip one of jar file and then get class to update the other one, suppose the have same code for EmailInfo class, so they can exchange with each other.

5. use this command to update the class in one jar file:

C:\SVN\….WEB-INF\lib>jar uf jar1.jar com\abc\EmailInfo.class

Then you can try to see result.

How to add data to SOAPHeader in the Web Service client code

By W.Zh   Mar 2014

Request

When you create a web service client proxy, after that, you want to insert some data in the SOAP header part, such as some security information, some user related or transaction information etc. how to do that in the WS java client code?

Solution

Use the
SOAPHandler to do this.

1. Create a SOAPandler  class to implement the handleMessage, inside this you can create your own SOAP elements structure and add to the SOAP header part. code is like this.


import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;

import java.util.Set;

import java.util.TreeSet;

import javax.xml.namespace.QName;

import javax.xml.soap.SOAPElement;

import javax.xml.soap.SOAPEnvelope;

import javax.xml.soap.SOAPFactory;

import javax.xml.soap.SOAPHeader;

import javax.xml.soap.SOAPMessage;

import javax.xml.ws.handler.MessageContext;

import javax.xml.ws.handler.soap.SOAPHandler;

import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {

  

    private static final String CLASS_NAME = “SOAPHeaderHandler”;

  

    public Set<QName> getHeaders() {

        return new TreeSet();

    }

    //<ns1:Security xmlns:ns0=”http://com.test.ws/”&gt;

    //       <ns1:userName>name here</ns0:userName>

    //     </ns1:Security>

    public boolean handleMessage(SOAPMessageContext context) {

        Boolean outboundProperty =

            (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

     

        if (outboundProperty != null && outboundProperty.booleanValue()) {

            SOAPMessage message = context.getMessage();

            try {

                SOAPEnvelope envelope =

                    context.getMessage().getSOAPPart().getEnvelope();

                SOAPHeader header = envelope.getHeader();

                SOAPFactory factory = SOAPFactory.newInstance();

                String prefix = “ns1”;

                String uri = “http://com.test.ws/&#8221;;

                SOAPElement securityElem =

                    factory.createElement(“Security”, prefix, uri);

                SOAPElement nameElem =

                    factory.createElement(“userName”, prefix, uri);

                String na = “Name here”;

                nameElem.addTextNode(na);

                securityElem.addChildElement(nameElem);

                // if no header, add one

                if (header == null) {

                    try {

                        header = envelope.addHeader();

                    } catch (SOAPExceptionImpl se) {

                      se.printStackTrace();

                    }

                }

                header.addChildElement(securityElem);

            } catch (Exception e) {

                e.printStackTrace();

            }

        } else {

            // inbound

        }

        return true;

    }

    public boolean handleFault(SOAPMessageContext context) {

       

        return true;

    }

    public void close(MessageContext context) {

        //

    }

}

2.  Then you can use the Jdev to create a Web server proxy client code. at the client code, after you get the server, you can setup the handler chains before you can the method in your WS.

YourWebservice yourWebservice=
new YourWebservice(new URL(yourWSDLAddress),
new QName(“http://………………&#8221;,
“YourWebservice”));

//add header for SOAP
yourWebservice.setHandlerResolver(new HandlerResolver() {
  public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList =
new ArrayList<Handler>();
handlerList.add(new SOAPHeaderHandler());
return handlerList;
}

});

3. Please note that
new YourWebservice(new URL(yourWSDLAddress), new QName(“http://………………&#8221;,”YourWebservice”));
is be used to define the dynamic WSDL URL.
 

 

How to change IP/host and other varibles for SOA application deployment

By W.Zh Jan 2011

Issue:

When I create a soa compisite application, which mostly includes some WS call, needs the wsdl end point host, port for URL… then your BPEL process run against the WS. But when u deploy from jdevelpoer you found you can not change your WSDL host and port info, as all these ip and port are used in the composite.xml in the app… It can not change after u deploy.  So u can not deploy to a new server to run the WS end point.

Solution: 

In fact, this is a very basic issue in SOA, but initially we think this is very hard thing. SOA developer guide introduces something called configuration plan file. In fact it is a XML can let u replace these variables in the composite.xml for different deployment. You can read the SOA dev guide 41.6 chapter to use the jdev to create and edit the configplan file.  When u deploy from Jdev, u can refer to use what config plan file for a deployment.

When u deploy from WLS EM console UI, in the SOA admin guide chapter 5, you can point to use a config plan file to define this deployment uses what plan file to replace these variables.

Based on this plan file, you can also use OUI to collect the user input for these replaces, in the OUI install steps, and then u change the plan file content in OUI and make your application installtion can fit user’s server enviroment. And also if you deploy from ant, you can use the plan file too.

This is very useful!.