Showing posts with label spring boot. Show all posts
Showing posts with label spring boot. Show all posts

May 27, 2016

Pass arguments to your main method in gradle bootRun

If you are tired of Spring Boot configuration magic, there is one more trick to confuse you completely.
How to configure Spring to work without knowing profile or environment? Dropwizard style, like this:
java -jar myjar.jar myconfig.yml.
No profiles, no wandering how did my properties got populated.

Spring Boot first class configuration is Java bean. Unfortunately, due to legacy issues, we need to include xml config. After some pain, suffering and reading, I found solution:
@ImportResource("classpath:application-context/applicationContext.xml")
//@Component
public class BatchConfiguration 

In similar way you can include properties file.
Next step is ${properties}. In xml configuration there are some environment-specific properties, like database url and so on. Some advise JNDI, but it introduces one more layer of magic - configuration of a web container.
So, question is, how to populate properties with external config. There are a ton of solutions out there, but none worked for me. Maybe because it's Spring Boot+Spring Data+Spring Batch or maybe because I don't understand this page. Anyway, I found my own way:
    
public static void main(String[] args) throws IOException {
        if (args.length >= 1) {
            Properties p = new Properties();
            p.load(new FileReader(args[0]));
            p.forEach((x, y) -> {
                System.setProperty((String) x, (String) y);
            });
        }
        SpringApplication.run(Application.class, args);
    }
Now it works perfectly in fatJar task, but what about bootRun? Boot Run saves a lot of dev time and is very easy to use. As you probably know, BootRun extends gradle standard JavaExec task, with awesome parameter args. It goes straight to your main method. So gradle bootRun task looks like:
bootRun {
    args =["cars-etl.properties"]
    
}
This is all for make your solution work! Have fun.
P.S. HowTo pass jvmArgs
P.P.S. HowTo run job from Controller

Apr 29, 2016

Spring Data Mongo Criteria Example

spring-data-mongodb-1.8.4 has a great package , with some features that makes mongodb queries easy. Unfortunately, documentation on this topic is not very good. I'll contribute to it by short example.

Problem

We want to search mongodb using $and and $in keyword based on several fields. But we don't know field configuration beforehead. Input params are fit into domain class:
public class MakeModelYear {
    private String[] make;
    private String[] model;
    private String[] year;

    public MakeModelYear(String[] make, String[] model, String[] year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public String[] getMake() {
        return make;
    }

    public String[] getModel() {
        return model;
    }

    public String[] getYear() {
        return year;
    }

    public boolean isEmpty() {
        return isEmpty(model) && isEmpty(make) && isEmpty(year);
    }

    public static boolean isEmpty(String[] a) {
        return a == null || a.length ==0;
    }
}
Any of make model and year can be null, and we still need to have nice smooth functionality

Solution

For Criteria object:
   public static Criteria generateQuery(MakeModelYear key) {
        Queue cril = new ArrayDeque<>();
        if (!MakeModelYear.isEmpty(key.getMake())) {
            Criteria makeCri = Criteria.where("Make").in(Arrays.asList(key.getMake()));
            cril.add(makeCri);
        }
        if (!MakeModelYear.isEmpty(key.getModel())) {
            Criteria modelCri = Criteria.where("Model").in(Arrays.asList(key.getModel()));
            cril.add(modelCri);
        }
        if (!MakeModelYear.isEmpty(key.getYear())) {
            Criteria yearCri = Criteria.where("Year").in(Arrays.asList(key.getYear()));
            cril.add(yearCri);
        }

        return cril.size() == 1 ? cril.poll() : cril.poll().andOperator(cril.toArray(new Criteria[]{}));
    }

For Query itself object:
        MakeModelYear key = new MakeModelYear(make, model, year);
        Query query = new Query();
        if(!key.isEmpty())query.addCriteria(DaoHelper.generateQuery(key));
        query.fields().exclude("_id");
        return mongoTemplate.getCollection(CARS).find(query.getQueryObject(), query.getFieldsObject()).toArray();

As you can see, we can specify both Criteria and configuration what to return and what to supress in one readable object.
I could not find better way in Jongo and mongo driver.

Feb 12, 2016

Dropwizard vs Spring Boot


In Java world there are 2 most wide spread solutions for JSON REST technology. In this post I’ll cover some aspects of them, that seems of most importance to me. 

Dependency Injection

With Spring, you are limited to Spring DI - quite complex and hard to debug. With Dropwizard, you can choose any DI you like. I was using Guice. But beware of using javax.inject annotations. Dropwizard v0.9.2. uses fresh release Jetty, that was build using HK2 DI library. So, using  general annotations with some other DI solution may result in strange behavior. For Guice-HK2 there are some bridge solutions, but using DI library specific annotations will save you from trouble.

Rest Api

I personally find JAX-RS specification not very convenient, maybe because I prefer single routes file and dislike annotating classes with @Path. Spring annotations for REST API are slightly better in this regard.

Configuration

Dropwizard offers once convenient way to configure everything - yml. With Spring you have as much flexibility as you can handle, and it makes server hard to maintain. I guess Dropwizard configuration is more in line with java values - there is single way to do it, simple, clear,maintainable. In case of issue you always know where to look.

Deployment

Dropwizard oriented on jar-deployment, standalone jetty. Spring can do both jar and war (for tomcat). It is arguable, but I consider multiple deployment options as a plus - it doesn’t complicate maintenance much, but can simplify support in case of running multiple applications.

Static Resources & Templates

Dropwizard offers quite simple way to mix pages and JSON API. If we will use angular on client side - it result in quite elegant solution with no tweaks. With Spring Boot I've struggled to configure my application to work with HTML and JSON, with support of some static ( e.g. css) resources.

SummaryTable

This is my marks for different aspects of platform. Max mark is 5. The bigger-the better.

CriteriaDropwizardSpring Boot
DI53
REST API34
Configuration53
Deployment45
Static Resources & Templates53
Total
2218





Summary
Dropwizard is better IMHO, and it plays nice with most Spring projects, like Spring Security and Spring JDBC. Spring Boot probably more performant, but I have no data on this topic, and all performance depends mostly from performance of your database. Solutions are quite similar, so winner detected.
There are lots of other articles on topic, that cover slightly different areas than this one.