How to have custom mapper keys in your documents with Jongo

Posted: décembre 31st, 2013 | Author: | Filed under: Dev, Java, Jongo, MongoDB, NoSQL, Tutorial | No Comments »

I’m giving a try to Jongo to replace spring-data-mongodb in a project but I have to manage documents with ‘not really java compatible keys’.
For example, a key with a first upper case letter and some ‘-’ inside … (well ok that’s ugly but I can’t change that now).

In spring-data, I’m using MappingMongoConverter, it works but Jongo seems to be easier to use and deploy than spring data.

And yes, it’s very simple to customize the way Jongo manages your beans !
The reason is that Jongo uses Jackson Mapper (by default but you could use your own or favorite one).
So, you just have to create a PropertyNamingStrategy !!!

1 – Create a NamingStrategy

With this naming strategy, we just search in a map if there’s a replacement value for the provided key.

package com.ezakus.data.jongo.customs;

import static com.fasterxml.jackson.databind.PropertyNamingStrategy.PropertyNamingStrategyBase;

import java.util.Map;

public class MapTransformNamingStrategy extends PropertyNamingStrategyBase{

    private static final long serialVersionUID = 1L;

    private Map<String, String> mapping;

    public MapTransformNamingStrategy(Map<String, String> mapping) {
        this.mapping = mapping;
    }

    @Override
    public String translate(String property) {
        if (mapping.containsKey(property)) {
            return mapping.get(property);
        }

        return property;
    }
}

2 – Use it with Jongo

As you could see in the Jongo documentation :

Jongo comes with a custom Jackson configuration that can be extended.

So you just have to use addModifier and a MapperModifier implementation to set your naming strategy to the mapper.

package com.ezakus.data.jongo.customs;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.jongo.marshall.jackson.configuration.MapperModifier;

import java.util.HashMap;
import java.util.Map;

public class CustomMapperModifier implements MapperModifier{
    Map<String, String> mapping = new HashMap<String, String>();

    public CustomMapperModifier(){
        mapping.put("myProperty", "custom-key-for-my-property");
    }

    @Override
    public void modify(ObjectMapper objectMapper) {
        objectMapper.setPropertyNamingStrategy(new MapTransformNamingStrategy(mapping));
    }
}
Jongo jongo = new Jongo(db, new JacksonMapper.Builder().addModifier(new CustomMapperModifier()).build());

3 – Full example

Here is a DummyObject class to test :

package com.ezakus.data.jongo.document;

import org.bson.types.ObjectId;

public class DummyObject {

    private ObjectId id;
    private String myProperty;

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public String getMyProperty() {
        return myProperty;
    }

    public void setMyProperty(String myProperty) {
        this.myProperty = myProperty;
    }
}

And a unit test (I’m using an embedded mongo for the test)

package com.ezakus.data.jongo.document;

import com.ezakus.data.jongo.customs.CustomMapperModifier;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.MongodConfig;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
import org.jongo.Jongo;
import org.jongo.MongoCollection;
import org.jongo.marshall.jackson.JacksonMapper;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.net.UnknownHostException;

import static org.fest.assertions.Assertions.assertThat;

public class NamingStrategyTest {

    public static MongodExecutable mongodExe;
    public static MongodProcess    mongod;

    @BeforeClass
    public static void runBeforeAllTests() throws Exception {
        MongodStarter runtime = MongodStarter.getDefaultInstance();
        NamingStrategyTest.mongodExe = runtime.prepare(new MongodConfig(Version.Main.V2_0, 12345, Network.localhostIsIPv6()));
        NamingStrategyTest.mongod = NamingStrategyTest.mongodExe.start();
    }

    @AfterClass
    public static void runAfterAllTests() {
        NamingStrategyTest.mongod.stop();
        NamingStrategyTest.mongodExe.cleanup();
    }

    @Test
    public void testNaming(){
        DB db = null;
        try {
            db = new MongoClient("localhost", 12345).getDB("myDB");

            Jongo jongo = new Jongo(db, new JacksonMapper.Builder().addModifier(new CustomMapperModifier()).build());

            MongoCollection dum = jongo.getCollection("dummies");
            assertThat(dum.count()).isEqualTo(0);

            DummyObject d = new DummyObject();
            String prop = "where is brian ?";
            d.setMyProperty(prop);

            dum.save(d);
            assertThat(dum.count()).isEqualTo(1);

            DummyObject check = dum.findOne("{custom-key-for-my-property: '"+prop+"'}").as(DummyObject.class);
            assertThat(check.getId()).isEqualTo(d.getId());
            assertThat(check.getMyProperty()).isEqualTo(prop);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

}

Compiling and installing Hyperdex from sources with Java and YCSB bindings on Debian

Posted: août 2nd, 2012 | Author: | Filed under: BigData, Dev, Java, Linux, NoSQL, Tutorial | No Comments »

After a lot of hours I finally succeed to build Hyperdex on a Debian with Java and YCSB bindings.

1 – Apt sources

Edit /etc/apt/sources.list and add backports packages

deb http://backports.debian.org/debian-backports squeeze-backports main

If you don’t have contrib and non-free for the main line, add them :

deb http://debian.mirrors.ovh.net/debian/ squeeze main contrib non-free

Add the Hyperdex repository

wget -O - http://debian.hyperdex.org/hyperdex.gpg.key \
  | apt-key add -

wget -O /etc/apt/sources.list.d/hyperdex.list \

http://debian.hyperdex.org/hyperdex.list

Update

apt-get update

2 – Install dependencies

apt-get install git openjdk-6-jdk build-essential libcityhash-dev libgoogle-glog-dev \
libpopt-dev libpo6-dev libe-dev libbusybee-dev python python-dev python-pyparsing \
python-setuptools python-argparse cython swig2.0 autoconf automake autoconf-archive libtool pkg-config gperf
easy_install sphinx
wget https://github.com/downloads/brianfrankcooper/YCSB/ycsb-0.1.4.tar.gz
tar zxf ycsb-0.1.4.tar.gz
export CLASSPATH=`pwd`/ycsb-0.1.4/core/lib/core-0.1.4.jar
git clone git://git.hyperdex.org/po6.git
git clone git://git.hyperdex.org/e.git

cd po6
autoreconf -i; ./configure; make && make install
cd ..

cd e
autoreconf -i; ./configure; make && make install
cd ..

3 – Install Hyperdex

git clone git://git.hyperdex.org/HyperDex.git

cd Hyperdex
autoreconf -i; ./configure --enable-java-bindings --enable-ycsb; make && make install