Friday, February 21, 2014

Call by name using Java 8 Supplier

A call by name example in the Functional programming course offered through Coursera is the following:

def loop: Boolean = loop 

def and(x: =>Boolean, y: =>Boolean) = if (x) y else false

and(false, loop)  

Here loop is a non-terminating recursive call. "and" is a function which takes two call by name expressions, and when "and" is called with "loop" as a parameter the call does not blow up, as loop is evaluated only when required.

Now, a similar code, though not this elegant, can be written using Java 8 Lambda expressions.

First the non-recursive looping expression:

 Boolean loop() {
  return loop();
 }

The following "and" method simulates call by name semantics by taking Java 8 Functional interface "Supplier" as the parameters, each supplier evaluates to a Boolean.

 Boolean and(Supplier<Boolean> x, Supplier<Boolean> y) {
  if (x.get()) return y.get();
  else return Boolean.FALSE;
 }

and finally the call to "and":

and(() -> false, this::loop)

The call uses Lambda expressions, the first "Supplier" simply returning false, the second Supplier a call to loop using method references. In this case, like with Scala, the call does not blow up as the second parameter is only evaluated when the first expression is true - since the call is with the first expression being false, it evaluates cleanly to "false".

Again the Java 8 equivalent is not as elegant as Scala, but works well enough.

Wednesday, February 12, 2014

Spring Integration Standalone application with Spring Boot

I had earlier blogged about a way to write a standalone Spring Integration application. Spring Boot makes creating this standalone application much simpler.

The simple flow was to poll the USGS service providing information about the earthquake activity around the world and to log this information. The flow described using Spring Integration is the following:

 <int:inbound-channel-adapter channel="quakeinfotrigger.channel" expression="''">
  <int:poller fixed-delay="60000"></int:poller>
 </int:inbound-channel-adapter>
 
 <int:channel id="quakeinfo.channel">
  <int:queue capacity="10"/>
 </int:channel>

 <int:channel id="quakeinfotrigger.channel"></int:channel> 

 <int-http:outbound-gateway id="quakerHttpGateway"
     request-channel="quakeinfotrigger.channel"
     url="http://earthquake.usgs.gov/earthquakes/feed/geojson/all/hour"
     http-method="GET"
     expected-response-type="java.lang.String"
     charset="UTF-8"
     reply-timeout="5000"
     reply-channel="quakeinfo.channel">     
 </int-http:outbound-gateway>
 
 <int:logging-channel-adapter id="messageLogger" log-full-message="true" channel="quakeinfo.channel" level="ERROR">
  <int:poller fixed-delay="5000" ></int:poller>
 </int:logging-channel-adapter>




Pre-boot, the way to write a main program to start this flow would have been along these lines:

package standalone;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Main {
 public static void main(String[] args) {
  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/httpgateway.xml");
  applicationContext.registerShutdownHook();
 }
}

With Spring-boot however the configuration is IMHO simpler:

package standalone;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:httpgateway.xml")
public class Main {

 public static void main(String[] args) {
  SpringApplication.run(Main.class, args);
 }
}

And with this change, along with the spring-boot-maven-plugin plugin, the application can be started up this way:

mvn spring-boot:run

I had a very small hand in fixing this start-up script by contributing a change to the plugin to start-up the application without needing to manually run the compilation step first.


Even better, the spring-boot-maven-plugin provides tools to package the entire application into a executable jar which gets triggered during the package phase, along the lines of shade plugin:

mvn package 

and the executable jar run this way:

java -jar target/si-standalone-sample-1.0-SNAPSHOT.jar

An updated project with this change is available at this github location - https://github.com/bijukunjummen/si-standalone-sample