12/21/15

Polyglot Programming with Java and Scala in the Eclipse

Scala is a very powerful programming language that has full support for functional programming and besides provides programming with the widely-used object-oriented paradigm. After you delve into the details of the Scala and learn, you begin to search for the similar features and abilities in your favorite programming language.

Scala source code is intended to be compiled to Java bytecode. So that the resulting executable code runs on a Java virtual machine( JVM ). In the recent years, JVM-based languages like Scala, Groovy, Clojure... are becoming more popular and they provide more capabilities and characteristics than Java itself has. So I think, it triggers the Java to enhance and polish up with extra features. For example, in the Java8, lambda expressions allow us to use functional programming notations in Java. But in the other JVM languages, similar features already exist for years.

Luckily, if you are Java developer, you have a chance to use Scala with Java and make polyglot programming. Scala is interoperable with Java and Java libraries may be used directly in Scala code. In this post, I will explain how to code in Scala and Java in the same project in the Eclipse IDE.

First of all, you should install the "Scala IDE" plug-in in your Eclipse. In a basic project, I will put Java and Scala codes in the project and use Java code in the Scala code and likewise vice versa. I will illustrate it step by step.

1) Create Project

In the Eclipse, create a new "Scala Project" going via "File" -> "New" -> "Scala Project". Create "src/main/java" source folder for Java codes and "src/main/scala" source folder for Scala codes. After applying them, the project layout in the Eclipse is seemed like this:

2) Create Packages

Create a Java Package in the "src/main/java" source folder and a Scala Package Object in the "src/main/scala" source folder. I name them "polyglot.java" and "polyglot.scala", respectively:

3) Add a Scala Class and a Java Main method

I create a "RationalNumber" scala class into the scala package. This class includes a "constructor" that gets the numerator and denominator parts of the rational number, "add" and "toString" functions.

package polyglot.scala

class RationalNumber( num : Int, dem : Int ) {
    
  def numerator = num
  def denominator = dem
  
  def add( added : RationalNumber ) = new RationalNumber( this.numerator *
      added.denominator + added.numerator * this.denominator, this.denominator *
      added.denominator )
    
  override def toString = this.numerator + "/" + this.denominator  
}

I add a Java class with a "main" method to start the execution of the code. The main method imports the "RationalNumber" Scala class. As you see, in the Java code we can use a Scala code.

package com.ilkerkonar.scalaAndJava.java;

// import the Scala class here.
import polyglot.scala.RationalNumber;

public class TestMain {

    public static void main(String[] args) {
        
        RationalNumber r1 = new RationalNumber( 3, 5 );
        
        System.out.println( r1 );
        
        System.out.println( r1.add( new RationalNumber( 1, 3 ) ) );        
    }
}

4) Import Java Code in the Scala Code

We imported the Scala code in the Java code. Now on the contrary, we use Java code in the Scala code. In the "RationalNumberCalculator" Java class, there is an implementation of the rational number subtraction operation:

package polyglot.java;

//Import the Scala code.
import polyglot.scala.RationalNumber;

public class RationalNumberCalculator {
    
    public RationalNumber sub( final RationalNumber minuend, final RationalNumber subtrahend ) {
        
        return new RationalNumber( minuend.numerator() * subtrahend.denominator() - 
            subtrahend.numerator() * minuend.denominator(), 
            minuend.denominator() * subtrahend.denominator() ); 
    }
}

We revise the "RationalNumber" Scala class and import the "RationalNumberCalculator" Java class. It is Java code usage in the Scala code sample.

package polyglot.scala

// Import Java code
import polyglot.java.RationalNumberCalculator

class RationalNumber( num : Int, dem : Int ) {
    
  def numerator = num
  def denominator = dem
  
  // Instantiate a Java class as a Scala variable.
  val rationalNumberCalculator = new RationalNumberCalculator()
  
  def add( added : RationalNumber ) = new RationalNumber( this.numerator *
      added.denominator + added.numerator * this.denominator, this.denominator *
      added.denominator )
    
  override def toString = this.numerator + "/" + this.denominator  
  
  // Define a Scala function that invokes a Java method
  def sub( subNumber : RationalNumber ) = rationalNumberCalculator.sub(this, subNumber)
}

In the main method, we can also exemplify the "sub" function call:

package com.ilkerkonar.scalaAndJava.java;

// import the Scala class here.
import polyglot.scala.RationalNumber;

public class TestMain {

    public static void main(String[] args) {
        
        RationalNumber r1 = new RationalNumber( 3, 5 );
        
        System.out.println( r1 );
        
        System.out.println( r1.add( new RationalNumber( 1, 3 ) ) );        

        System.out.println( r1.sub( new RationalNumber( 1, 3 ) ) );        
    }
}

Finally, we obtain the output of the Main method execution like below:

   3/5
   14/15
   4/15

Conclusion

We can use Java and Scala programming languages interchangeably in the same project. We can download full source code and the Eclipse project here: ScalaWithJava.zip

1/30/15

Spring Retry Sample

A few days ago, I needed to build a retry mechanism in my project. I could get network exceptions while invoking a web service. Typically, I planned to put my code snippet in a "while loop", define a counter variable and controls the loop with maximum retry count condition.

Suddenly I claimed that it should be a different structure or a good pattern for the retry. I searched on the Internet and encountered Spring Retry library. I could not find a good tutorial or sample, but I implemented my own code with the help of simple examples in the Spring Batch documentation 

For the Spring Retry library, you can add the dependency below into your pom.xml file:
<dependency>
   <groupid>org.springframework.retry</groupid>
   <artifactid>spring-retry</artifactid>
   <version>1.1.2.RELEASE</version> 
</dependency>
Spring Retry helped me in my project. I am overjoyed to use it. Now I would like to share my know-how with a sample application. In my real-world applications, I regularly establish a retry mechanism in the web service clients in order to make more robust processing. Web service servers sometimes can't response in a while because of the network bottlenecks or instantaneous internal server errors. So the current transaction fails. In the sample application, I did not indicate a web service client implementation. To keep simple, I simulated it:

@Service
public class WebServiceClientSimulation {

 
private static final String  SIMULATION_RETRY_STR  = "yes";

 
@Autowired
 
Environment          env;

 
public String invoke() throws ApplicationException {

   
// Simulate the implementation
   
System.out.println( "Web Service was called and executed" );

   
if ( env.getRequiredProperty( "simulation.retry" ).equals( SIMULATION_RETRY_STR ) ) {

     
// An internal error has been occurred
     
throw new ApplicationException();
   
}

   
return "success";
 
}
}

In the Spring Retry, the main Interface class is RetryOperations. The simplest general purpose implementation of RetryOperations is RetryTemplate. The retry system is configured with the RetryTemplate class. BackoffPolicy class determines the waiting rules when a failure happens. I use FixedBackOffPolicy subclass. With this policy, fixed time interval is set between two retries. Inside a RetryTemplate, the decision to retry or fail in the execute method is determined by a RetryPolicy. SimpleRetryPolicy subclass of the RetryPolicy just allows a retry on any of a named list of exception types. In my example, I configured the SimpleRetryPolicy with a fixed retry max count. ExceptionClassifierRetryPolicy class allows to configure different retry behavior for an arbitrary set of exception types. In my sample, I decide to match the "SimpleRetryPolicy" with my custom ApplicationException class. Exception class and its RetryPolicy counterpart are kept in a map. Then this map is set to ExceptionClassifierRetryPolicy class as a general policy for all the Exceptions. With the help of the policy map, you can determine the retry policy for each exception type.

@Configuration
@ComponentScan
@PropertySource
( "classpath:application.properties" )
public class ApplicationContext {

 
@Bean
 
public FixedBackOffPolicy getBackOffPolicy( final Environment env ) {

   
final FixedBackOffPolicy policy = new FixedBackOffPolicy();
    policy.setBackOffPeriod
( Long.valueOf( env.getRequiredProperty( "retry.interval" ) ) );

   
return policy;
 
}

 
@Bean
 
public ExceptionClassifierRetryPolicy getRetryPolicy( final Environment env ) {

   
final Map< Class< ? extends Throwable >, RetryPolicy > policyMap =
     
new HashMap< Class< ? extends Throwable >, RetryPolicy >();

   
final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
    simpleRetryPolicy.setMaxAttempts
( Integer.valueOf( env.getRequiredProperty( "retry.count" ) ) );

   
// Determine the policy per exception
   
policyMap.put( ApplicationException.class, simpleRetryPolicy );

   
final ExceptionClassifierRetryPolicy retryPolicy = new ExceptionClassifierRetryPolicy();
    retryPolicy.setPolicyMap
( policyMap );

   
return retryPolicy;
 
}

 
@Bean
 
public WebServiceClientSimulation getWebServiceClient() {
   
return new WebServiceClientSimulation();
 
}
}

I put the application variables in a property file. "Simulation.retry" property controls and decides the test scenario. If the value of this property is "yes", An exception is thrown in the "WebServiceClientSimulation" class, otherwise "success" response is returned and no exception is occurs and RetryTemplate does not produce any retry. So I can test both success case and failure and retrying case. Property file content:

retry.interval = 3000
retry.count = 3
simulation.retry = yes

In the ApplicationService class, I instantiated a RetryTemplate variable. I set the BackoffPolicy and RetryPolicy and call the web service client with retry. There are some posibble "execute" overload methods:

 T execute(RetryCallback retryCallback) throws Exception;

 T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback)
    throws Exception;

 T execute(RetryCallback retryCallback, RetryState retryState)  
    throws Exception, ExhaustedRetryException;

 T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback,
    RetryState retryState) throws Exception;

I implemented the second one. First is the RetryCallback class and the second is RecoveryCallback class parameters. After every retry struggle, the "doWithRetry" method of the RetryCallback is called. After all the retry attempts are reached at the max number count, the last call is done to the "recover" method of the RecoveryCallback class.

@Service
public class ApplicationService {

 
@Autowired
 
private FixedBackOffPolicy        fixedBackOffPolicy;

 
@Autowired
 
private ExceptionClassifierRetryPolicy  exceptionClassifierRetryPolicy;

 
@Autowired
 
private WebServiceClientSimulation    webServiceClientSimulation;

 
public String callTheWebService() {

   
final RetryTemplate retryTemplate = new RetryTemplate();

   
// Retry configuration
   
retryTemplate.setBackOffPolicy( fixedBackOffPolicy );
    retryTemplate.setRetryPolicy
( exceptionClassifierRetryPolicy );

   
try {
     
// Call the web service with retry
     
return retryTemplate.execute(
        (
RetryCallback< String, ApplicationException > ) retryContext ->
          webServiceClientSimulation.invoke
(),
        retryContext ->
"Unsuccess. The retry reached maximum retry count :"
         
+ retryContext.getRetryCount() );
   
} catch ( final ApplicationException e ) {
     
e.printStackTrace();

     
return "Exception was been occurred";
   
}
  }

 
public void setFixedBackOffPolicy( final FixedBackOffPolicy fixedBackOffPolicy ) {
   
this.fixedBackOffPolicy = fixedBackOffPolicy;
 
}

 
public void setExceptionClassifierRetryPolicy( final ExceptionClassifierRetryPolicy exceptionClassifierRetryPolicy ) {
   
this.exceptionClassifierRetryPolicy = exceptionClassifierRetryPolicy;
 
}

 
public void setWebServiceClientSimulation( final WebServiceClientSimulation webServiceClientSimulation ) {
   
this.webServiceClientSimulation = webServiceClientSimulation;
 
}
}

You can see that I made the inner class implementations with Java8 lambda expressions. Lambda expressions ( Or closures ) are arguably the most exciting and significant new feature with the Java 8 release. The introduction of lambdas enables to use aspects of functional programming, making your code be more concise and flexible. Without lambda expressions, the implementation seems like this:

    try {
     
// Call the web service with retry
     
return retryTemplate.execute( new RetryCallback< String, ApplicationException > () {
         
@Override
         
public String doWithRetry( RetryContext retryContext ) throws ApplicationException {
           
return webServiceClientSimulation.invoke();
         
}     
        }
,
       
new RecoveryCallback< String >() {
         
@Override
         
public String recover( RetryContext retryContext ) throws Exception {
           
return "Unsuccess. The retry reached maximum retry count :"
             
+ retryContext.getRetryCount();
         
}
        })
;
   
} catch ( final ApplicationException e ) {
     
e.printStackTrace();
 
     
return "Exception was been occurred";
   
}   

If you set "yes" as the value of the "simulation.retry" property and "3" as the value of the "retry.count" property, the output of the main method is below:

Web Service was called and executed
Web Service was called and executed
Web Service was called and executed
Unsuccess. The retry reached maximum retry count :3

I hope this gives you some thoughts about Spring Retry. If you have any question, please do not hesitate to contact. My email address is ilker@ilkerkonar.com. All the code that I have demonstrated here is also available in my Github repository: https://github.com/softengilker/draftApplications/tree/master/SpringRetrySample