Should I regret

I face some rather odd challenge in my current job (this is my second job). Most of the challenge really didn’t come from the job itself, but more likely the people I work with. Sometime I even ask myself should I regret choosing this career. Questioning myself if my whole life is a lie.

That’s jQuery (?)

Once awhile, one of my colleague came to me and ask something about some project I am working on. He saw this:

<h1>${mytitle}</h1>
${some_content}

in a jsp file. He said: “Oh, jQuery, I didn’t use that”.

He is not a fresh grad, he had 3 years of web development experience, not like he don’t know jsp, java is exactly what he work with before. I am lucky because I don’t have to explain to him what is expression language.

I’m not familiar with javascript

Few months back, I was struggling with the workload. My superior decided to distribute my work to some “experience” staff. So, I went ahead to explain what my project is all about. At first it feel like a normal briefing and he show some weird look when I show him the javascript part (well 90% of it). When my superior went and ask about how was the task been assigned to him. “I don’t even know what he talking about, it’s all javascript, I don’t even know how to help in this project.”. That came out from a < 5 years experience senior.

Let’s pretend I know what he is talking about

Still, I wish I don’t have to do this, but the project is experiencing scope creep (thanks to some “yes man” during requirement gathering). My project have to be split apart (yet again) to some other staff to achieve the timeline (at least management think it work that way).

Same old story, I had to explain what I done so far and what left to be done. I told my partner about some technical detail which make use of some feature in java EE 6. His response was like understand nothing yet keep nodding. May be it is a bad idea using java ee platform beyond web profile.

P/S:

I am not writing this post to show off how capable I am or how incompetent my colleague was. I am just stating some fact. Experience staff is doesn’t mean they are competent. Or, they don’t really wish to learn or re-learn some practice.

I saw them keep on writing scriptlet in JSP. Abusive usage of collection utility instead of writing POJO. Writing Stateful utility and more. They even write entire transaction logic in a controller class (Servlet).

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