Comparison between JS+REST and JSF

This post shares various rationale in choosing between JavaScript+Rest Or JSF (Java Server Faces) for Webapplication development.
The modern web technologies has brought in plethora of java-script frameworks which helps in building responsive UI. JSF is component MVC, which is a part of standard JEE stack, and an end-to-end webframework by itself with access to multiple JEE components.
The JS+Rest and JSF are matured and they are their best with their scopes.

Comparison Criteria: The below is the elaborate criteria for comparing both the frameworks but there can also be more comparison scenarios based on specific business use cases.

Organisational Criteria:These criteria effects more or less organisational capability to handle the current application through out its life time.

  • Popularity and Community support: There are multiple JS libraries/client MVC frameworks like ReactJS,AngualJS which are very popular and have strong community support. JSF implementations like Primefaces also have strong community support.
  • Support: Considering the large community support availability both models have equal support possibilities. On weighing individual options JSF based frameworks have better support when compared to Ajax+rest as there are backed by framework founder companies.
  • Documentation: The documentation for the framework directly affects the developer productivity. Any matured frameworks like AngualarJS, Primefaces, ReactJS are very well documented.
  • License: This directly effects the overall cost of the product throughout its life time. Most of the frameworks are free to use if no commercial support is required.
  • Availability of resources: The skill of available resources directly effects the overall project time-line and cost. This is more subjective to kind of organisation, for a java shop company JSF is better suited, where as for front end companies JavaScript+Rest are better suited.
  • Learning curve: The skill of available resources directly effects the overall project time-line and cost. JSF is general has higher learning curve when compared to javascript, but for a expert component MVC developer JSF has lesser learning curve than pure front end technologies.
  • Productivity: This dependencies on the skill of resources, if a java developer with exposure to component MVC, can use existing tooling and be more productive with JSF. Front end developer will be more productive than JSF developers due to their exposure to stack and lesser tooling required for development and white box tests.
  • Page Complexity: Does page complexity demands huge flashy responsive UI of javascript.

Technical Criteria:These criteria effects QOS(Quality of Service) requirements and few other technical criteria of the application.

  • Sustainability: Sustainability is an ability to remain productive indefinitely with providing value to stakeholders and ensuring safe world for all the stakeholders. One of the key criteria under sustainability is carbon foot print. This is more to do with web page design than a base framework. Considering mobile first apps with lesser content and faster page loads can be more sustainable. Primefaces JSF 2 framework which is powered by jquery can also be as comptent as JS+rest apps in building relatively similar page loads. In general Ajax+rest is expected to have lesser http requests, but badly designed application can have more ajax requests resulting in detrimental of sustainability.
  • Security: Any server side framework like JSF is more secured than pure client side framework. At the same time the badly designed JSF application can be less secure than good designed javascript application.
  • Life-cycle complexity: JSF life cycle is more complex when compared to JS frameworks.
  • Back-end Integration: JSF is only suited if back-end is java applications. For non java technologies java script or their back end native frameworks are undisputed choices.
  • Supported protocols: JSF supports HTTP and Web-Socket(JSF 2.3+) protocol. JavaScript being executed throw browsers so most of the browser supported protocols can be extended for javascript apps.
  • Routing options: JSF is multiple page framework where routing can be declared programatically or xml configurations. Client side JS MVC frameworks like angualarjs also provide routing options for SPA.
  • Data binding: JSF has a better support for databinding when the entire workflow from web view to database is considered. JS frameworks has data binding only to html view and an additional data binding implementation is needed on server side.
  • Project Modularity: We have build pipelines like gulp/grunt available for JS frameworks also which helps in including modularity for JS scripts. But there is always a need of additional modularity model needed for business logic. For JSF applications front-end and back-end being same technology can have standard modular approach.
  • White Box Testing Tools: JavaScript has better whitebox test tools as no specific deployment needed. JSF applications need special embedded containers for white box testing.
  • Server resource usage: JS applications uses lesser server IO and CPU when compared to JSF applications. If primefaces applications are planned with proper client side validations/converters server CPU usage can be drastically reduced.
  • Client resource usage: JS applications uses higher client resources when compared to JSF as more amount of processing is done on client machines.
  • Scalability: JS applications are better scalable as they are of stateless in nature when compared JSF applications which are by default stateful.
  • Mobile: JSF implementations like Primefaces has built mobile UI support which can be leveraged to build mobile first JSF applications. The JS is better suited for mobile apps because of its intrinsic client side centric language.
  • Cloud compatability: JS applications can connect to cloud endpoints. Any JEE applications can be deployed in cloud. JSF 2.X which has path based resource handling and bookmark facility simplifies cloud based resource handling.
  • Post-Redirect-Get: Starting from JSF 2.X, there is cleaner way to implement this pattern on server side. Modern client MVC consider ajax workflows and do not cleanly support this pattern, there can also be technical argument where people claim its not needed for ajax workflows.
  • Browser memory: This mostly depends on the implementation rather than on framework. JS applications has better fine grained control on profiling and minimising the memory usage. JSF developers need to rely mostly on the used framework vendors like Primefaces to resolve the issues.
  • Network usage: Properly designed JS applications uses lesser network when compared to JSF applications where server state need to be maintained.
  • DOM rendering: JS libraries like ReactJS has better performance when compared to pure JSF applications.
  • Client Side validations: JS frameworks by default provides support for client side validations. JSF frameworks like Primefaces support most of the client side validations bringing JSF very near to JS applications.
  • Browser compatibility: JS frameworks as well as JSF implementations support major modern web browsers. The support is only limited to the components provided by the frameworks and any incorrect implementation of basic html elements may result in incorrect display.
  • Auto-Complete: Most of the JS frameworks and JSF implementations provide components for Auto-Complete.
  • Responsive UI: Most of the modern JS frameworks are built for implementing responsive UI. JSF frameworks like primefaces provided specialized css for responsive UI, but developer need to ensure they are used correctly for yielding better results.

Comparison Criteria:

Based on the above criteria the selection of framework mostly depends on the specific business case and organisational culture. On a general note it can be considered that
JSF is better if:

  • Back-end is JEE application.
  • Its application with max users ranging around 10000 users and do not expect to be scalable into 100’s of 1000’s users.
  • A business application where business rules are of more preference than flashy UI.
  • Training is imparted to business users for the application usage.

Ajax+Rest JS applications is better if:

  • Back-end can be non java application.
  • End user is unknown.
  • The application need to scale exponentially.

Advertisements

Protect Java sources from Reverse Engineering

Overview

If we are developing java application whose byte code is publicly distributed over internet, there is always possibility to reverse engineer the class files using various decompilation tools.
To make reverse engineering much difficult, Java obfuscators can be used.
Java obfuscators will ensure to replace the identifiers to names which are unclear and also make the flow very difficult to understand after decompilation.
There are multiple free and commercial Java obfuscators whose list can be found here.
The current post deals with obfuscation process using Proguard.

Pre-requisites

  • Jdk installed, can be downloaded here
  • Java decompiler, the current post uses JAD, can be downloaded here. JAD is currently outdated and doesn’t support latest jdk enhancements
  • Java obfuscator, the current post uses Proguard, can be downloaded here.

Sample source file

The below is sample java source files (NoObsfuscation.java and ObfuscationImpl.jav) which will be explained in current post, other sample files can be found here.

	public class NoObsfuscation {

	public static void main(String[] args) {
		ObfuscationInterface obfuscationInterface = new ObfuscationImpl();
		obfuscationInterface.printInput("obfuscation interface instance");
		obfuscationInterface.printDefaultMthd();
		
		ObfuscationImpl obfuscationImpl = new ObfuscationImpl();
		obfuscationImpl.genericAbstractMethod();
		obfuscationImpl.genericImpl();
	}
}
public class ObfuscationImpl extends AbstractObfuscation implements
		ObfuscationInterface {

		public void printInput(String input) {
		System.out.println("printInput implementation:--->"+this.hashCode());
	}

	@Override
	public void genericAbstractMethod() {
		System.out.println("genericAbstractMethod:-->"+this.hashCode());
	}

Obfuscation Steps with Proguard

  • 1. Create Proguard Conf flile

  • The proguard conf file provides configuaruon details to be considered while obfuscation. The below mentioned are few config details and complete list can be found here.

          # The input jar which need to be obfuscated.
            -injars  core-java.jar
    
          # The obfuscated jar. 
            -outjars core_java_obfuscated.jar
    
          # The java source library jar which is the run time jar for code execution.
            -libraryjars "C:/Program Files/Java/jdk1.8.0_25/jre/lib/rt.jar"
    
          # Proguard provides map file which provides mapping between original java source identifiers and obsfuscted names for trouble shooting  and debugging purpose.
            -printmapping proguard.map
    
          # Proguard removes the unused and unreferenced sources to reduce the size of obfusctaed file. dontshrink options instructs proguard to retain all the files without removing them.
            -dontshrink
    
         # This file is not obfuscated and considered as root of the current references
           -keep public class com.siva.mythoughts.obfustcation.NoObsfuscation { *; }
    
         # This ensures all the files with below mentioned package are not obfusctaed and remain in tact
           -keep class com.siva.mythoughts.executorservice.* { *; }
    
         

  • 2. Execute Proguard

  • The proguard can be executed via command line Or it can also be executed during build process using Maven.
    The successful execution of proguard results in out jar as well as map file

            Execute via Command line
            C:\obfuscation\proguard5.2.1\proguard5.2.1\bin>proguard.bat @../examples/myconfig.pro
         
    	<profiles>
     	  <profile>
    	    <id>obfuscatedemo</id>
      	    <build>
      	     <plugins>
      		<plugin>
      		   <groupId>com.github.wvengen</groupId>
      		   <artifactId>proguard-maven-plugin</artifactId>
      		   <version>2.0.11</version>
      		   <executions>
      		     <execution>
      			<phase>package</phase>
      			<goals><goal>proguard</goal></goals>
      		     </execution>
      		    </executions>
      		   <configuration>
      			<outjar>core_java_obfuscated.jar</outjar>
      			<options>
      		 	   <option>-dontshrink</option>
      			   <option>-dontwarn</option>
      			   <option>-keep public class com.siva.mythoughts.obfustcation.NoObsfuscation { *; }</option>
      			   <option>-keep class com.siva.mythoughts.executorservice.* { *; }</option>
      			</options>
      		    </configuration>
      		</plugin>
      	     </plugins>
      	   </build>  		
    	</profile>
         </profiles>
         

  • 3. Decompiled sources

  • Find below the comparison between decompiled sources after and before obfuscation.

           import java.io.PrintStream;
           // Referenced classes of package com.siva.mythoughts.obfustcation:
           //            b, c
           public class NoObsfuscation
           {
    public NoObsfuscation()
        {
        }
    
        public static void main(String args[])
        {
            (args = new b()).c();
            args.a_();
            args = args = new b();
            System.out.println((new StringBuilder("genericAbstractMethod:-->")).append(args.hashCode()).toString());
            System.out.println("Generic Abstract Implementation");
        }
    }
    
    package com.siva.mythoughts.obfustcation;
    
    // Referenced classes of package com.siva.mythoughts.obfustcation:
    //            ObfuscationImpl, ObfuscationInterface
    
    public class NoObsfuscation
    {
    
        public NoObsfuscation()
        {
        }
    
        public static void main(String args[])
        {
            ObfuscationInterface obfuscationInterface = new ObfuscationImpl();
            obfuscationInterface.printInput("obfuscation interface instance");
            obfuscationInterface.printDefaultMthd();
            ObfuscationImpl obfuscationImpl = new ObfuscationImpl();
            obfuscationImpl.genericAbstractMethod();
            obfuscationImpl.genericImpl();
        }
    }
    
  • 4. Proguard Map file

  • The below is the proguard map file which can be used for debugging and troubleshooting purpose.

        com.siva.mythoughts.obfustcation.AbstractObfuscation -> com.siva.mythoughts.obfustcation.a:
        void <init>() -> <init>
        void genericImpl() -> a
        void genericAbstractMethod() -> b
    
        com.siva.mythoughts.obfustcation.NoObsfuscation -> com.siva.mythoughts.obfustcation.NoObsfuscation:
        void <init>() -> <init>
        void main(java.lang.String[]) -> main
    
        com.siva.mythoughts.obfustcation.ObfuscationImpl -> com.siva.mythoughts.obfustcation.b:
        void <init>() -> <init>
        void printInput$552c4e01() -> c
        void genericAbstractMethod() -> b
    
        com.siva.mythoughts.obfustcation.ObfuscationInterface -> com.siva.mythoughts.obfustcation.c:
        void printInput$552c4e01() -> c
        void printDefaultMthd() -> a_
    		

Limitations of Obfusction

  • Obfuscation process doesnt change the name of java API classes, they are still visible in decompiled obfuscated code
  • Dynamic generated classes obfuscation may create instability in the program execution
  • Obfuscation of life cycle call back methods may create instability during call backs
  • Serialized classes are not obfuscated
  • Further enhanced releases of the software should ensure to maintain compatibility with previous released obfuscated code
  • Some of the obfuscators may change the code work flow which may prevent jvm optimizations
  • Some anit virus softwares may alert obfuscated code as malicious

Jinfo Java Command Line Utility

Overview

jinfo is command line utility which gets the configuration information of running jvm process. It can also be used to set some of the jvm configuration parameters at runtime.

Usage Commands:

  • Jinfo help:

    JAVA_HOME/bin/jinfo –h
  • Display all the non default vm parameters and system parameters for specified process id (pid):

    JAVA_HOME/bin/jinfo pid
  • Display VM parameters details:

    JAVA_HOME/bin/java -XX:+PrintFlagsFinal

Display Configuration Info using jinfo:

  • Display VM flags used by specified jvm process:

    JAVA_HOME/bin/jninfo  -flags pid
  • Display all the system properties used by specified jvm process:

    JAVA_HOME/bin/jninfo  -sysprops pid

help_vm_sysprops

Retrieve and Modify Configuration Info using jinfo:

  • Display current value of specified vm parameter:

    JAVA_HOME/bin/jninfo  -flag MaxHeapSize 1872
  • Set boolean value vm parameter. Plus sets the value whereas minus removes it:

    JAVA_HOME/bin/jninfo  -flag +HeapDumpOnOutOfMemoryError 1872
  • Set specified value to non-boolean vm parameter:

    JAVA_HOME/bin/jninfo  -flag MaxHeapFreeRatio=50 1872
  • Manageable parameters exposed via DiagnosticMbean can only be set at runtime using jinfo

  • If a parameter could not be set by any of the above commands we get error message “Command failed in targe VM”

modifyParams

Conclusion:

jinfo is experimental feature offered in java which is prone to changes in future versions. The changes done via jinfo can also be modified via jconsole

Heap Dump Generation

Overview:
Java memory model consists of Heap memory, Thread stacks, Perm gen area.
Heap is memory area which is used for allocating memory for class instances and arrays are created.
Heap dump is snapshot of java objects and classes in memory at that point of time.

Create Heap dump using JConsole:

  • Open the java process in JConsole which is under jdk../bin.
  • Navigate to MBeans tab.
  • Select the Operation section of the com.sun.management/HotSpotDiagnostics object.
  • Enter p0 as HeapdumpPath and p1 as true/false for running GC before running heapdump.
  • Click heapdump.

jconsole

Create Heap dump using Visualvm:

  • Open the visual vm under jdk../bin.
  • On left hand margin, select your corresponding java process.
  • Right click on the process.
  • Create heap dump.

visualvm

Create Heap dump using Java Opts parameters:

  • Include -XX:+HeapDumpOnOutOfMemoryError while starting jvm process, which creates heapdump on out of memory.
  • Include -XX:HeapDumpPath while starting jvm process, to specify the heapdump file location.
  • \bin\java” -Xmx128M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath= CreateOOM
  • On out of memory exception, dump file will be created at specified folder with java_pid.hprof
  • Sample program to create OOM.
public class CreateOOM {

	public static void main(String args[]) {

		while(true) {
			int[] iarray = new int[Integer.MAX_VALUE];
		}

	}
}

Create Heap dump using Jmap:

  • Navigate to jdk\bin directory
  • jmap -dump:format=b,file=\mymemorydump.hprof

Create Heap dump using java program:

  • Heap dump can be dumped using java program via HotSpotDiagonistic mbeans, which is used by Jconsole also.
  • The below program creates heap dumps for current jvm.
import javax.management.MBeanServer;
import java.lang.management.ManagementFactory;
import com.sun.management.HotSpotDiagnosticMXBean;

public class DumpHeap {

	public static void main(String args[]) throws Exception {
	    String HOTSPOT_MBEAN = "com.sun.management:type=HotSpotDiagnostic";
		MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        HotSpotDiagnosticMXBean mBean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_MBEAN, HotSpotDiagnosticMXBean.class);
		mBean.dumpHeap("<pathOffolder>/pheap.dmp",true);
	}

}
  • The heap dump can also be executed programmatically by executing jmap command from within the program, in this scenario we can generate heap dumps based on pids.
import java.lang.management.ManagementFactory;
public class ExecuteJmap {

	public static void main(String args[]) throws Exception {
		String pid = args[0];
		String[] cmd = { "jmap", "-dump:file=<folder>/heapdump.bin", pid };
		Process p = Runtime.getRuntime().exec(cmd);

	}
}

Create Heap dump using MAT:

  • Heap dumps can also be executed via MAT directly for local jvm process
  • Click File –> Acquire Heap Dump
  • Select jvm process.
  • Select destination folder for heap dump
  • Click Finish

mat

Conclusion:
In addition to the above options, most of the application servers expose their own Mbeans, which can be executed via jython scripts to generate heap dumps.

Garbage Collector Types

Overview

Every object that is created in java is stored in heap space.
The allocation and de-allocation of memory spaces for the objects is executed by automatic garbage collection process triggered by JVM.
Based on the flavor and version of JVM, different garbage collection algorithms are available in JVM, which can be specified via jvm parameters.
Java uses generational heap space where the referenced objects are transferred across different generations and garbage collection triggered based on heap space generational role which is termed as minor GC and major GC.

Types of Garbage Collectors

  • The Serial Garbage Collector.
  • The Parallel Garbage Collector.
  • The Concurrent Mark Sweep Garbage Collector.
  • The G1 Garbage Collector.

The Serial Garbage Collector.

As the name specifies here minor and major gcs are done serially using single CPU.
During the gc process all other application threads are paused.
This uses mark-compact-collection method, there by which moves existing object references to beginning of heap so that new memory allocations are done in single continuous chunk at the end of heap.

    Relevance:

This is suitable where we have minimal memory and few cores.
This can also be suitable where more JVMs than the available cores are executed on same machine.
This being stop-of-world process and single-threaded may not be suitable for server environments which demands high-throughput/better responsiveness.

    Jvm arguments::

    -XX:+UseSerialGC - turns on serial garbage collector.

The Parallel Garbage Collector.

This is also called throughput collector.
This uses multiple threads for accelerating garbage collection process.
During the gc process all other application threads are paused.
Based on java version used there are two jvm arguments for parallel gc.
This process reduces the overall time spent by the application for garbage collection.

    Relevance:

This is mostly useful for jvm process executing on multi core machines.
This collector is more suitable for batch jobs and more database intensive query operations.<

    Jvm arguments::

-XX:+UseParallelGC or -XX:+UseParallelOldGC  turns on parallel garbage collector.

Note: By default based on jvm version enabling one of the flag automatically enables the other flag unless it is disabled

The Concurrent Mark Sweep Garbage Collector.

This is also referred as concurrent low pause collector.
CMS uses the same parallel GC algorithm for younger generation objects.
This uses multiple threads to trace the reachable objects to identify objects for marking and removal.
The CMS garbage collector pauses the application threads during initial-marking (mark live objects reachable by gc roots) and re-mark (objects that become un-referenced after initial marking) phases.
All the remaining garbage collection process like tracing and sweeping of live objects run concurrently with application threads.
The CMS garbage collector uses more CPU resources than parallel garbage collector but with relatively lower pause times.

    Relevance:

This is suitable for applications with large tenured generation objects and has more CPU resources.
This is required for applications which need higher responsiveness like web applications/services.

    Jvm arguments::

  -XX:+ UseConcMarkSweepGC - turns on CMS  garbage collector

The G1 Garbage Collector.

The G1 collector is parallel, concurrent and incrementally compacting low pause garbage collector.
This also operates concurrently together with application threads.
G1 collector does compaction of heap space on every cycle where as CMS does compaction only on stop the world process.
Other garbage collector uses fixed sizes for each generational heap space where as G1 uses different heap approach where heap is portioned into equal sized regions which are allocated to different generational roles based on demand, this approach provides better flexibility in heap allocation.
This heap distribution approach of G1 helps in having relatively lesser heap sizes.
G1 prioritizes its collection from the areas which has maximum reclaimable heap regions there by yielding maxing free space after gc.
G1 also has more predictable pause times as it can select the regions for gc which may fit into the configured pause interval.

    Relevance:

This is mostly suitable for applications with has large heap and need predictable low gc pause times.

    Jvm arguments::

 -XX:+UseG1GC - turns on G1 garbage collector.

Conclusion.

Each garbage collector can be fine tuned by configuring various jvm arguments which are specific to each gc collector type.
Java Ergonomics introduced in jdk 1.5, decides on default values for jvm parameters based on available system resources.
We can configure and fine tune these default values by overriding various jvm arguments, which will be mainly required when running multiple jvms on the same machine.

Also Read: