JAXB the life saver

My most recent assignment is to integrate all of the client’s pricing service and deliver a price comparison service. When I generating the service stub from the WSDL provided (Yeap, it’s SOAP). It generate a strange little interface method which look like this:

public String doStuff(String input);

This is weird, why it expected a string, I thought they require more input than a simple string. I tried to generate the stub again, of course, nothing changed.

So, after communicating with their IT team, turn out, they do expected a string, a freaking xml string, with reason of they don’t have to worry on change in WSDL in future when extra input is required. So, I seek advice from my superior.

Hmm, quite brilliant, we don’t have to generate other client if there’s any changes on their service.

I can’t believe that’s his comment. Anyway, I am not going to hand craft xml. Since I can’t convince anyone that this design isn’t a good idea. Still, I am lucky to convince my boss to upgrade the JDK to version 1.6 (you read that right, we were using version 1.5 and it’s 2017)

Java Architect XML Binding come with JDK 1.6, it simplify the XML POJO conversion. With simple annotation I could serialize a POJO to XML string and vice versa.

@XmlRootElement(name="input")
public class SomeInputXml{
    private String id;
    private String name;

    @XmlElement(name="uuid")
    public String getId(){
        return id;
    }

    @XmlElement(name="name")
    public String getName(){
        return name;
    }
}

With about POJO with some jaxb annotation, I can form a xml look like so,

<input>
    <uuid>somevalue</uuid>
    <name>somename</name>
</input>

There’s more JAXB can do like adding attribute and ignore some property. And the process of marshaling POJO to XML is extremely simple as well.

//This object will hold all of the pojo's xml metadata.
//It is resource heavy to create
//meant to be create once and reuse everywhere
JAXBContext context = JAXBContext.newInstance(SomeInputXml.class);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(someObject,baos);
baos.toString();//with this step, I could easily form a xml String

JAXB is quite useful when some work on xml generation or reading is required. I used it to read some sort of xml configuration file handcrafted by my colleague and reuse the POJO since DOM API’s Document is not thread safe to share along.

A good place to instantiate a JAXBContext will be in a either Singleton or ApplicationScope producer bean.

@ApplicationScoped
public class SomeConfig{
    private JAXBContext context;
    @PostConstruct
    public void init(){
         //initialization
    }
     
    @Produces //Or you could give a Marshaller 
    public JAXBContext getContext(){
       return context;
    }

}

One thing to note that CDI ApplicationScoped is lazy, it will be instantiate once when the first call is invoke (in this case it will trigger by Injecting JAXBContext)

One could make it eager init by replacing it by EJB’s singleton and Startup together.

 

A work around on legacy code

Domain specific standard api.

The company I worked for offer Software As A Service to various company in the same industry. The system is old enough to accumulate tons of technical debts.
One of the most noticeable problem was the control of the software specification. For some reason, the system shared single code base yet all company do have their own custom specification. The way they handle this sort of requirement is as follow:

if(company.equals("companyA"){
    // do stuff specifically for company 'A'
}

As the result, the current code base is virtually impossible to maintain. The only benefit gain from this approach is that any change request by a particular company can be easily done in short amount of time.

Recently, I am assigned to write some web service to fulfill the new requirement launching this July. With the new requirement, the work flow of this particular domain is completely change and hence legacy code base reuse is not that simple (not to mention the code base is tightly couple with the runtime context e.g. HttpSession in servlet-api)

I face quite a lot of trouble when dealing with the old code base and decided to rewrite some core component with reuse-ability in mind. Since the application is written entirely with java + jsp (and run on TomCat 6). I ported the application to TomEE 1.7.4. (which require an update of jdk to version 1.6).

Context Dependency Inject (JSR-330) is the key to separation of concern. The way Java EE platform is pretty much what I want to do:

  1. Define a set of standard API and all the program will only have reference to this set of API (typically an interface, annotation or some abstract class). The CDI container will then inject the implementation of the API base which is exist in the classpath. (e.g. TomEE Plus come with OpenJPA but the application don’t have to be aware of the OpenJPA classes)
  2. Implement the API and package it with different jar.
  3. Deploy the jar to the server.
  4. The implementation will be picked up automatically during execution. ( Here’s the true power of dynamic binding)

One thing to note is that Java handle classes in a weird way (this is valid up till JDK 1.8). Every classes is actually loaded in a global scope and when there’s 2 jar with same class name inside (fully qualified name) the jar file. The class in the later jar will be register to the class path.

And now finally come to the title. Domain specific standard pattern. Put it in simple term, I copy the concept of Java EE platform and bring it to application level. The known problem here is that we shared same code base for every single client and created a big mess. The only way to fix this is to separate every client to its own package. Do note that this system is written back in 1999 (almost 18 from now). It is not feasible to migrate every company to its own code base.

The keyword here is domain specific. The company I work for is writing software to the insurance industry. And most insurance company will shared same domain context, (e.g. both required some specific underwriting check/review before creating a transaction)

The api can be as simple as:

public interface QuotationService{
    public List<Quotation> findQuotationByID(String id);
}

So, we got our standard API now. Let’s implement it:

public class CompanyAQuotationService implements QuotationService{
    @Override
    public List<Quotation> findQuotationByID(){
        //query and return
    }

}

The above class is suppose to be packaged in different jar file and deploy with the api file.

When we talk about polymorphism, some people do :

//class definition omitted

QuotationService service = new CompanyAQuotationService();

This is not helping at all. Since we still have reference to CompanyAQuotationService class, we didn’t really solve the coupling problem. Besides, the application will even failed during deployment time whe there’s 2 implementation of QuotationService, note that I mention 2 implementation, not 2 same class with same fully qualified name.

//within class scope
@Inject
QuotationService service;

The code above will run without any issue under application server (With CDI container). One should use setter injection instead for the ease of unit test (Mocking the host in particular).

Now we have our implementation for company A. Let say company B have some change request on quotation service.
We can simply write another implementation to do perform the customization.

public CompanyBQuotationService implements QuotationService{
     @Override
    public List<Quotation> findQuotationByID(){
        //query and return
    }
}

Note: the code above isn’t going to work if there’s 2 implementation in same classpath.

Dynamically inject the implementation

Now we introduce a qualifier annotation

@Qualifier
@Target({TYPE,METHOD})
@Retention(RUNTIME)
public @interface Company{
    String value();
}

A qualifier annotation is just a marker or id to allow cdi do more advance lookup during injection. Fortunately this is only required once.

@Company("A")
class CompanyAQuotationService implements QuotationService{
}

//another class
@Company("B")
class CompanyBQuotationService implements QuotationService{
}
//the executing class
@Inject
@Company("B")
private QuotationService service;//the company b instance will be injected here

This sort of implementation some what fit my needs. But still, there’s a need to specify which company to inject. Most of the time the application context will do checking on a global variable company, and customize system behavior base on this variable. What I want to achieve is as follow:

@Inject
SomeInjector injector;

QuotationService service=  injector.getInstanceOf(company);

And I found this answer on StackOverflow.

public class CompanyImpl implements Company extends AnnotationLiteral<Company>{
    public CompanyImpl(String value){
        this.value = value;
}
}
//The injector/factory

@Inject
@Any
Instance<QuotationService> quotationServicePool;// instance isn't really pool, but a pool of implementation seems logical

public QuotationService inject(String company) throws Exception{
    CompanyImpl impl =new CompanyImpl(company);
    return quotationServicePool.select(impl);
}

OK, this fulfilled my requirement on runtime injection. But this also introduce another problem, I have to write an injector for every single standard API.

My recent research found that Xtend’s active annotation might solve my problem.

P/S:

  1. I don’t think it is feasible to start a project like this (multiple company sharing same source), but I am working on a legacy project and have very limited choice. I assume this sort of design will consume relatively higher memory.
  2. Every single implementation jar file must have an empty beans.xml file in META-INF/ folder and WEB-INF folder in the web applications (true for Java EE 6, it’s enable by default in version 7).

References

Context Dependency Injection
AnnotationLiteral