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.

Apr 8, 2016

Hexagonal architecture and ESB (Enterprise service bus). Part 1.


This blog post will start comparing 2 architectural approaches. 

You probably have heard about ESB - architectural model to connect everything with everything. It's interesting for me to compare it to less known but quite interesting concept of Hexagonal architecture.
In enterprise there are usually a tons of interconnected services\applications, so let's evaluate these approaches from enterprise view.

Overview 

In a one sentence:
Hexagonal architecture(HA) - ‘’every’’ piece of functionality the application(service) offers is available through an API (application programmed interface) or function call.

Enterprise service bus(ESB) - mediator service that facilitates work of loosely coupled applications(services) that are expected to be independently deployed, running, heterogeneous, and disparate within a network.
 Nobody reads middle section, so I will leave it for next posts and jump directly to a conclusion.

Conclusion

Hexagonal architecture might seem less mature, but, compared to enterprise service bus, it provides a lot of practical benefits for multiple services integration. They might look uglier on a paper, but, in practice, they provide faster time-to-market software with better quality and simpler error handling.
Good news is, that HA is compatible with ESB, so I think best way is to use HA as a basic approach, adding some ESB as you need it.
In one sentence - design your application around your business domain, not integration solution.