Thoughts on SpringBoot

In its new avatar, Spring enters the opinionated frameworks marketspace, and finally takes the Sinatra/Scalatra/Ratpack/Dropwizard/Spark route, where embedded containers (ie no external server containers) will start dictating the future. Whats an opinionated framework anyway? Aint all frameworks opinionated? To me every piece of code is just as opinionated as the developer who wrote it. Here are my observations about SpringBoot, after having worked with it for about 6 weeks.

1. Build support for gradle (+)
SpringBoot apps can be built using both maven and gradle. But I believe Gradle will eventually dominate the world of buildscripts. So the sooner your team moves to gradle, better will be your quality of this life and perhaps, next life too. Are you listening, .Net?

2. Starter poms (+)
Remember your 500 line pom.xml, where the tag <dependency> occurs 25000 times? Say good bye and start using starter-poms. Combined with gradle, a typical build file is now about 30 lines.

3. Configurations (+/-)
Spring is among the last standing action heros of xml-based application configuration in jvm world. Super hit when introduced, but soon became a liability. Thankfully, many developers challenged the xml tag soup and created innovative web frameworks (Wicket, Play etc.). Those who work with the Spring-based framework Grails, may have not touched an xml for a good period of time. If Spring MVC developers are still stuck with Spring without adapting Grails, I fail to understand why (well except for business impositions).

Ironically, SpringBoot seems to have many opinions when it comes to configuration – it supports 3 flavors of bean configurations: xml, annotation and groovy dsl. Having worked with Grails and other non-xml based applications for the last few years, picking up SpringBoot was bit of a chore. Grails autowires beans by name, and when custom beans are required, there is this wonderful bean builder. For me, java annotations are no better than xml configuration. Xml configuration proliferates verbosity but annotations defeat the purpose of wiring objects separate from code. While it brings type-safety, it also lets you mix code, configuration and logic and I think its a total mess. Annotations are like antibiotics – good in small doses (@ToString, @RestController, @AutoClone etc.), too many side-effects with overdose – building whole applications using annotations is @NotMyStyleOfTea.

A typical SpringBoot application has many many annotations – @EnableAutoConfiguration, @Configuration, @ComponentScan, @Conditional etc. Sometimes you end up with more annotations than the code itself and its not intuitive which is doing what when how. SpringBoot is certainly simpler for developers from xml background, but to me as a Grails developer, annotations have been a bit intimidating and sprawling. I don’t see CoC (Convention-over-Configuration), instead I see CoC (Configuration-over-Code).

Thankfully, SpringBoot has great (although not 1:1 xml equivalent) support for groovy beans dsl (via the GroovyBeanDefinitionReader). Groovy dsl is elegant, concise, intuitve and very readable. For some loss of type-safety (which could have been compensated by good tooling support), it comes with a great punch – wiring beans, environmental configurations, programmatic startup logic (as opposed to declarative) etc. I feel Spring can standardize groovy bean as the only configuration mechanism and shed all the fat of xmls and annotations. It would make the framework pretty lean and competitive in the already crowding lean frameworks market. May be thats what grails-boot is?

4. Properties (+/-)
Just like configurations, there are a few ways of defining and injecting properties. Coming from Grails background, the many ways of injecting properties was a bit confusing. SpringBoot supports both .properties and .yaml files. AutoConfiguration uses many default values for properties, but there is no comprehensive documentation on these properties on whats default. Again there are many annotations related to properties @ConfigurationProperties, @PropertySource, @Value, @EnableConfigurationProperties etc. Grails has this amazing single-point grailsApplication bean based on ConfigObject (a glorified Map) and allows nested and runtime evaluate-able configurations – helpful in dynamic scenarios. Again I wish Spring had defacto support for this (injecting properties from a config.groovy).

5. Rest Support (+)
SpringBoot makes it very easy to create rest controllers via @RestController. Instead of creating full-blown web applications, Spring’s eco can be used to create well-rounded rest services backed by Batch/Data/Integration/Security and use js frameworks like Angular/Knockout/Backbone etc. for front end. If using rest over json, Groovy 2.3 is promising to come up with fast json marshaller. While I like the cleanliness of Thymeleaf, the modern js frameworks have a clear advantage over server-side html generators.

6. Logging (+/-)
Yet again, too many logging frameworks in the bag: log4j, log4j2, slf4j, slf4j2, commons.log, java.util.log, logback. I spent some time resolving dependency conflicts, until I finally gave up and switched to logback. Spring team strongly recommends logback – Just Go with it – there is probably a good reason.

7. Data Access (+)
No question about Spring’s versatility here. Name any db and you have SpringBoot autoconfiguration support. Plus the Grails team has done a great job of spinning-off Gorm to standalone component. TexMex, I would say.

8. Testing (+/-)
Many examples still show use of JUnit, but here is a good start on how to use the incredible Spock framework in SpringBoot. Spock is like mom’s recipe – once you taste it, others aint the best.

9. Documentation (+)
It has improved a lot with newer minor releases. It takes time to sift through some old examples in the community, but lets just blame Google for not knowing what you exactly want, though it seems to know all about what food you want to eat when you are near a restaurant.

10. Finally
I think Grails3 (grails-boot?) is going down the trending route of embedded container deployments. I think that’s the only thing against Grails in the current trend. SpringBoot has got there first but I still feel it lacks the simplicity of Grails or the leanness of Play. It has certainly been simplified, but not simple.

If your existing eco system depends a lot on Spring based frameworks, it is worthwhile to adapt SpringBoot. Honestly, Im hoping Grails3 isn’t far off!

Advertisements

The GroovySpringBootBatchGormGroovyDslBeanFactory

See spring-boot-batch-sample at github for the updated source code.

I was recently working on setting up a not-so-trivial Spring Batch application and wanted to use SpringBoot, because of its embeded-web container capabilities. I could have used Grails and Spring Batch plugin, but wanted to give an opportunity for our Ops/DevOps team a peek at running and maintaining apps via plain “java -jar”. I hadn’t used Spring since 2009 (switching between SharePoint and Grails). Xml is no more a necessity for Spring and it has good support for java annotation configuration. But I am not very comfortable with annotation oriented programming. Xml provided the separation of wiring dependencies from code, but its verbose. Annotations are less verbose, but allows to mix configurations, logic and code, which I feel can spiral out of control pretty soon. I still feel wiring dependencies independently of “code” is a very desirable feature for large applications. Both xml and annotations seem to be at opposite ends of the spectrum.

Fortunately there is a middle ground. SpringBoot provides support for Groovy beans dsl, via the GroovyBeanDefinitionReader. Groovy bean dsls solve the problems of xml and annotations: DI wiring + concise readable syntax + some logic (eg environment-based). But this comes at a price of loosing type-safety. I am surprised that groovy dsl has not yet gone mainstream with Spring apps. If Spring comes with a Groovy DSLD schema (may be there is one already?), it could be a killer feature. For example, Spring Integration is already offering a dsl based “workflow”, which is pretty elegant to read, write and maintain.

I was also new to SpringBatch so it took a while to get them all wired up. So here is a starting point, if you want to use Groovy lang + SpringBoot + SpringBatch + Groovy DSL + Gorm. I haven’t figured out dsl equivalents of @EnableScheduling and @Scheduled yet.

Part 1: appcontext.groovy

//Note that config is not defined as a bean, but directly evaluated and then injected into other beans
//the 'grailsApplication' equivalent
ConfigObject configObject = new ConfigSlurper().parse(Config)

//Note the syntax beans {} not beans = {} like in Grails resources.groovy
beans {

	xmlns([ctx: 'http://www.springframework.org/schema/context', batch: 'http://www.springframework.org/schema/batch'])
	ctx.'component-scan'('base-package': 'org.mypackage')
	ctx.'annotation-config'()

	myController(MyController) {
		config = configObject 
	}

	myService(MyService) {
		config = configObject 
  }

  //MyItemReader implements ItemReader
	myItemReader(MyItemReader) { bean ->
		bean.initMethod = 'init' //required if initializing some data from external dao
		bean.scope = 'step' //for job restartability
	}

	myItemProcessor(MyItemProcessor) {
		myService = ref('myService')
	}

	myItemWriter(FlatFileItemWriter) {
		lineAggregator = new DelimitedLineAggregator(delimiter: ',', fieldExtractor: new BeanWrapperFieldExtractor(names: ["id", "title"]))
		resource = '/apps/springboot/myproject/output'
	}

  //create a job
	batch.job(id: 'job1') {
		batch.step(id: 'step1') {
			batch.tasklet {
				batch.chunk(
					reader: 'myItemReader',
					writer: 'myItemWriter',
					processor: 'myItemProcessor',
					'commit-interval': 10
				)
			}
		}
	}

  //the following beans are minimum mandate because there is no equivalent of xml's <batch:job-repository /> in groovy dsl
  //http://stackoverflow.com/questions/23436477/groovy-bean-syntax-for-spring-batch-job-repository
  //thanks to https://github.com/johnrengelman/grails-spring-batch/blob/master/SpringBatchGrailsPlugin.groovy for the bean definitions
	jobRepository(MapJobRepositoryFactoryBean) {
		transactionManager = ref('transactionManager')
	}

	jobRegistry(MapJobRegistry) { }

	jobLauncher(SimpleJobLauncher) {
		jobRepository = ref('jobRepository')
		taskExecutor = { SyncTaskExecutor executor -> }
	}

	jobExplorer(JobExplorerFactoryBean) {
    //dataSource is auto-configured
		dataSource = ref('dataSource')
	}

	jobOperator(SimpleJobOperator) {
		jobLauncher = ref('jobLauncher')
		jobRepository = ref('jobRepository')
		jobRegistry = ref('jobRegistry')
		jobExplorer = ref('jobExplorer')
	}

}

Part 2: Application and Scheduler

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableScheduling
class MyJobApplication {

	private static final Logger logger = LoggerFactory.getLogger(MyJobApplication.class.getName())

	@Autowired
	JobLauncher jobLauncher

	@Autowired
	Job myJob

//  You can also create configObject bean like this and refer back in beans.groovy using ref('config')
//	@Bean(name="config")
//	ConfigObject configObject() {
//		return new ConfigSlurper().parse(Config)
//	}

	
  @Scheduled(fixedDelayString = '${myJobFixedDelay}', initialDelayString = '${myJobInitialDelay}')
	public void startMyJob() {
		logger.info "startMyJob()"
    //Add time if your job runs repeatedly on different parameters - this will make it an unique entry in the batch-job tables
		JobParameters jobParameters = new JobParametersBuilder().addLong("time",System.currentTimeMillis()).toJobParameters()
		jobLauncher.run(myJob, jobParameters)
	}

	public static void main(String[] args) {
		logger.info "Starting MyJobApplication..."
		Object[] sources = [MyJobApplication.class, new ClassPathResource("appcontext.groovy")]
		SpringApplication.run(sources, args);
	}
}

Part 3: Datasource

Datasource bean is autoconfigured via @EnableAutoConfiguration and if you define the application.properties (or application.yaml). Just add the right driver in your build.gradle. If you dont specify any, hsql db is used.

Part 4: build.gradle

buildscript {
	ext {
		springBootVersion = '1.0.2.RELEASE'
		spockVersion = '0.7-groovy-2.0'
	}
	repositories {
		mavenLocal()
		mavenCentral()
		maven { url "http://repo.spring.io/libs-snapshot" }
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'groovy'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
	baseName = 'myapp'
	version = '0.1'
}

repositories {
	mavenCentral()
	mavenLocal()
	maven { url "http://repo.spring.io/libs-snapshot" }
}

dependencies {
	compile("org.springframework.boot:spring-boot-starter-web")
	//if you want to use Jetty, instead of Tomcat, replace the above line with the next two lines
	//compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") { exclude module: "spring-boot-starter-tomcat" }
	//compile("org.springframework.boot:spring-boot-starter-jetty:0.5.0.M2")
	compile("org.springframework.boot:spring-boot-starter-actuator")
	compile("org.springframework.boot:spring-boot-starter-batch")
	compile("org.springframework.boot:spring-boot-starter-logging")
	compile("org.springframework.boot:spring-boot-starter-jdbc")

  compile("org.codehaus.groovy:groovy-all:2.2.2")
	
  compile("org.springframework:spring-orm:4.0.3.RELEASE")
  //For those Grails guys, just throw in the new and shiny standalone gorm dependency
	compile("org.grails:gorm-hibernate4-spring-boot:1.0.0.RC3") {
    //currently brings in spring-orm:3.2.8, exclude it and explicitly include new one above
		exclude module: 'spring-orm'
	}

	testCompile "org.springframework.boot:spring-boot-starter-test"
	testCompile "org.spockframework:spock-core:${spockVersion}"
	testCompile "org.spockframework:spock-spring:${spockVersion}"
}

task wrapper(type: Wrapper) {
	gradleVersion = '1.11'
}

A few more features for the future:

1. Defining multiple datasources in groovy dsl
2. Using spring-loaded for hot-swapping runtime (as of now I can’t get this to work with Intellij Idea)
3. Using Spring-batch-admin to control jobs via UI

Groovy #7 – if there is no if

The most minimal high level programming language just needs three statements:

  1. assignment
  2. if
  3. goto

All other syntaxes can be replaced with a combination of these. As programming languages evolved, goto bore the ignominy of being the first to lose favor with the programmer-theorists. It was replaced with various sophisticated constructs like for, while, do, switch, subroutines and functions.

The next one is the ‘if’ condition. With the applications growing in complexity, the if-s also drive the cyclomatic complexity. But to some extent, OOP languages eliminate if conditions at a higher-level.

Consider a simple example:

abstract class Animal {
abstract string voice();
}

class Dog extends Animal {
string voice() { return "Bark" }
}

class Cat extends Animal {
string voice() { return "meow" }
}

Animal a = new Dog()
assert a.voice() == 'Bark'

Without the inheritance feature, a procedural language programmer would have to rely on if condition to make the above work. Obviously the if condition is still there somewhere down the line (compiler will have to determine the type of the object to know which method to invoke), but its not in the reviewed code. Yet, the above looks like an elaborate code-trap to just avoid one if condition.

By induction, can ‘if’ conditions be fully replaced by abstractions? Lets look a simple Groovy example, which uses the metaprogramming technique to do something like that.

Boolean.metaclass.methodMissing = { name, args -> println args[0].call() }

def find_nativity_by_greetings(def greetings) {
greetings in ['howdy', 'hiya'] { 'Texan!' }
greetings in ['hola', 'buenos dias'] { 'Mi amigo!' }
greetings == null { 'Yankee' }
}

find_nativity_by_greetings('howdy')
//Result
Texan!

Since if conditions evaluate to true/false and are automatically represented as Boolean in Groovy, by providing a missingMethod override implementation for the anonymous closure and calling that closure, the “if” keyword vanishes from code. The above construct is now equivalent to a if..elseif..elseif..elseif.. construct.

How is this helpful? The above constructs can actually be written in a configuration file by a business owner or it could even be in a excel spreadsheet. The core Groovy code just has to slurp the config file, evaluate and execute the statements as if there are no if-s.

Groovy OLC #1 – Prime Numbers

It is interesting how formatting conventions keep changing with the programming languages. I’m not talking about naming conventions, but just text formatting conventions aka code-layout conventions.

In Java, you dont commonly see beginning separate braces in a new line, although its okay for the ending braces. While in .NET, its a norm to have curly braces in separate lines. Inline code is also very rare in Java and .NET, except for get and set, but in Groovy/JavaScript, it seems to be a very common occurrence. Some of these conventions evolve as a tradition and some right from the invention. In Pascal, structured code was considered art. In Python block indentations are obligatory. Code format conventions, just like naming conventions are very subjective and sometimes personal and if a team cannot agree on one, its a rough road. Although some modern IDE-s have smartened up and present the personalized formatted code to the developer, while the source control would store a standard version. Some of the preferences are driven by language features too.

Closures, especially compact ones, are very intriguing when presented in a single line and some times very challenging. Solutions to puzzles and problems when rewritten in a single line look very catchy. Those who have coded in Prolog would perhaps realize what it means to say that a piece of code is work of art. You can do a regular findBy logic in Prolog, but doing it “Prolog”-way via predicates is certainly challenging.

So here is a One-Liner-Closure (OLC) that calculates the prime numbers > 2.

Given: a list of natural numbers
Find: all the prime numbers

void find_prime_numbers() {
def list = 1..100
println list.findAll { x -> (2..Math.sqrt(x)).every { x % it != 0 } }
}

Result:
[3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Enter-prise Java or Enter-the-dragon Java?

Java frameworks have become penny a dozen with no end in sight of any java developer not dissatisfied with any given frameworks. Every other framework claims it is better than the other one, because its APIs provide much flexibility. The truth is no framework provides a complete solution.

Debates on decisions on which framework to use has pretty much become part of a new enterprise project.  JSF is pretty heavyweight? Can Spring’s  xml configuration pretty soon get out of control ? Is mixing @Annotations, column names, field lengths, constraints, primary key, foriegn key, join columns in the POJO a really good approach ?  (One of these days we shall have an annotation to have all the data within the pojo.  Everyone wants Ajax behaviour now. Is Tapestry worth it or will Tapestry 6 be a complete rewrite yet again ? May be just stick to servlet and JSP ? How about EJB3 and reliving its nightmares ? Flex anyone ?

Blogs and Forums are full of debates about Spring vs Seam, JSF vs SpringFaces, Struts vs Tapestry, Yin vs Yang frameworks. There are people who adore JSF and there are who abhor JSF. I dont think its anybodys fault. It probably has to do more with how the brains are wired. Left brained guys like JSF, while the right brained guys like Spring. Or vice-versa.

Two of the technologies I have been tracking very actively recently are Wicket and Groovy.

When I start writing code using Wicket, Im reminded of my Swing days – oh how nice for a change it is to write ONLY in Java? Instead of all the lame scriptlets of two line Java codes thrusted into html (JSP), opening curly braces in header.jsp and closing it in catch.jsp. Or XMLs containing Java like code (like ActionScript). Or XMLs defining flows and subflows with hard-to-follow ELs. Im realizing that JSP is really an insult to a good programmer’s intelligence and XML is an insult to human capacity to understand languages. Is XML the “human readable format for machines” ? Duh?

There are other component frameworks like Wicket, but Wicket’s simple, easy to understand API really is cool and intuitive. No WTextField or WLabel .. its simply TextField or Label. That simplicity makes a lot of difference. It just wires to the brain quickly. No xmls or logic in the views. Whew! Models and Nesting models take a bit to understand, but it can reduce cyclomatic code complexity quickly. With Model 2 architecture, most of the OO stuff in Java has been relegated to extending MyServiceImpl from AbstractServiceImpl and a few inheritances here and there. Wicket changes all that. It lets the HTML itself be designed with inheritance, encapsulate components and hide unwanted details. 

Groovy meanwhile is what can be termed as the “Missing Java Functions”.

I hope Wicket grows quicker and Groovy’s feature-set start attracting more developers. After all programming is an art and it is all about enjoying the art.