Wednesday, September 17, 2014

Compatibility and API Evolution in Java

Jens Dietrich (MSc and a PhD in Mathematics from the University of Leipzig) visited melbJvm meetup at 8th of September, 2014. He explained about his research topic "Compatibility and API Evolution". It was really interesting and here are some major points which was discussed on this topic.

        Programs not developing from scratch means, most of the programs using libraries , frameworks , ects and they compose using APIs which are providing by libraries. There are few points need to consider when updating APIs in libraries. 
Will the programs work when re-compile with new library ? or is it possible to replace the new library without compile?


So compatibility is coming this place and there are three type of compatibility issues may occur when updating libraries.




  • Source compatibility - Program is source compatible with library if Program can be compiled with that library(ex lib-2.0.jar)
  • Binary compatibility - Program is binary compatible with library if Program can be linked with that library without recompile
  • Behavioural compatibility - Behavioural compatibility includes the semantics of the code that is executed at runtime
Following are the practical definition for Source vs Binary compatibility

     A program is source compatible with a library lib.jar if the program uses the library, and compilation succeeds: javac -cp ..,lib.jar,.. …
A program is binary compatible with a library lib.jar if it links and runs with this library: java -cp ..,lib.jar,..
Source compatibility is checked by the compiler and binary compatibility is checked by the JVM

Examples for Source vs Binary compatibility

  • Adding a Method to an Interface

 Both source and binary compatible
  • Removing a Method from an Interface 

Binary compatible and source incompatible. Because recompilation fails as Main.bar() does not override a method!
  • Specialising Return Types 

Binary incompatible but source compatible 
  • Generalising Parameter Types 
Binary incompatible but source compatible 
  • Change a Method from Static to Non-Static
Both source and binary incompatible. what will be for "Change a Method from Static to Non-Static" ?
  • Primitive vs Wrapper Types

Binary incompatible but source compatible
  • Generics
Binary compatible but source incompatible
  • Constants
Binary compatibility but binary behavioural incompatible
  • Adding a Runtime Exception
Source compatible,s binary compatible and binary behavioural incompatible
  • Adding a Checked Exception

 Source incompatible,binary compatible and binary behavioural incompatible

You can find more scenarios in following Jens Dietrich's video lecture at meljvm


slides to download : Link 1 

Sunday, January 12, 2014

Redirection inside @PostConstruct vs preRenderView event

I tried to implement the logic which is needed to redirect when page loading. I have used EJB (3.0) and JSF (2.1)  technologies here.
Initially I used @PostConstruct method with @ViewScoped in ManagedBean.


import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; @ManagedBean(name = "redirectTest") @ViewScoped public class RedirectTest implements Serializable { @PostConstruct public void init() { if (isRedirect) { ExternalContext context = FacesContext.getCurrentInstance() .getExternalContext(); try { context.redirect(context.getRequestContextPath() FacesContext.getCurrentInstance().responseComplete(); } catch (IOException e) { e.printStackTrace(); } } }
It throws following exception

com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean redirectTest at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:229) .... Caused By: com.sun.faces.spi.InjectionProviderException: com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke public void redirectTest.init() on bean class class redirectTest with args: null at com.bea.faces.WeblogicInjectionProvider.invokePostConstruct(WeblogicInjectionProvider.java:40) at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:223) ... Caused By: com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke public void redirectTest.init() on bean class class redirectTest with args: null at com.oracle.pitchfork.inject.Jsr250Metadata.invokeLifecycleMethod(Jsr250Metadata.java:395) ... Caused By: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) .. Caused By: java.lang.IllegalStateException: Response already committed at weblogic.servlet.internal.ServletResponseImpl.objectIfCommitted(ServletResponseImpl.java:1651) ...
 
Above exception has given message as “Response already committed”.  Response is already committed means ,it has been sent first few bytes as response from server to client. This is a point of no return. This happen when the backing bean is referenced (and thus constructed) for the first time relatively late in the view, maybe about halfway or in the end. For example


 (1) Bytes already sent to response 
 (2) Point when managedbean created ( if @ViewScoped )

It can not be solved even close the response manually using

FacesContext.getCurrentInstance().responseComplete();

Use the preRenderView method execute during the beginning of the render response phase, right before the HTML is been rendered. The @PostConstruct is intented to perform actions directly after bean's construction and the setting of all injected dependencies and managed properties such as @EJB, @Inject, @ManagedProperty, etc. The injected dependencies are namely not available inside the bean's constructor. This will thus run only once per view, session or application when the bean is view, session or application scoped. The preRenderView event is invoked on every HTTP request (yes, this also includes ajax requests!).

Solution : preRenderView
By using preRenderView will give the solution for this scenario.

Refer this post about best place for the f:metadata element : post

There is the issue , preRenderView might calling more than one time when using with . This can be avoid using
public void init(){ if (!FacesContext.getCurrentInstance().isPostback(){ //put initView codes here }
JSF 2.2 onward "f:viewAction" tag, which is supposed to replace this "f:event type="preRenderView", it will however be possible with the onPostback attribute:

"f:viewAction action="#{defaultNewQuestionHandler.init}" onPostback="false" "