Archive

Author Archive

Encrypting an external drive

July 26th, 2015 No comments

I wanted to encrypt the disks that I use to regularly make a backup so I can put it offsite without that nagging thought that just about anyone can read it’s contents when it gets stolen/lost.

Find out the name of the disk you want to encrypt. I usually use a ‘sudo fdisk -l’ to find out which disk. In my case /dev/sdc3 so I will use that in this example. Substitute with your own unless you want to lose data.

Make sure your disk is not mounted:

sudo umount /dev/sdc3

It is good practice to fill the disk with some initial garbage to make any decryption attempts harder.

sudo dd if=/dev/urandom of=/dev/sdc3

Initial creation:

# Login as root
sudo -i
# Install cryptsetup
apt-get install cryptsetup
# I am using a passphrase to setup the encryption you could optionally use a keyfile. Check out the manual for more info.
cryptsetup -y create crypt /dev/sdc3
# Create an ext4 filesystem. (-m 0 -> No reserved blocks for root, this is an external disk)
mkfs.ext4 -m 0 /dev/mapper/crypt
# Create a directory to mount to and mount
mkdir /mnt/crypt && mount /dev/mapper/crypt /mnt/crypt

Remounting:

sudo cryptsetup create crypt /dev/sdc3
sudo mount /dev/mapper/crypt /mnt/crypt

That did it for me. I just wanted a small barrier to chase away curious people.

Categories: Debian, Ubuntu Tags: ,

Tomcat – High CPU Breakdown

June 5th, 2015 No comments

Determine the process id (PID) of the process that has high CPU load.

The culprit:

16397 tomcat    24   0 2809m 1.2g  26m S 197.4 14.8 112:28.42 java

Use top, ps or the java jps tool. I used jps here.

sudo -u tomcat jps -l

Output:

16397 org.apache.catalina.startup.Bootstrap
8985 sun.tools.jps.Jps

We then try to create a thread dump with the java jstack tool.

sudo jstack 16397 > stacktrace.dmp

Output:

16397: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding
sudo jstack -F 16397 > stacktrace.dmp

If that is also not working you can try quitting the process.

sudo -u tomcat kill -QUIT 16397

You will need to check the logs to see the stacktrace.

You can then check out the running threads and their state. I found that some threads were in a blocking state due to a few java.lang.OutOfMEmoryError errors.

To get more detailed information we can also use the jmap command to do a little deeper digging.

sudo jmap -dump:file=thread_dump.16379.dmp -F 16397
Categories: Linux Tags:

Java import certificate from website

April 9th, 2015 1 comment

Making calls to a server with a self signed certificate might give you the following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

To fix this we need to import the certificate of this website into our local keystore.

Default pw for the keystore is ‘changeit’.

openssl s_client -showcerts -connect www.example.com:443 < /dev/null | openssl x509 -outform DER > www.example.com.der
keytool -importcert -trustcacerts -alias www.example.com -file www.example.com.der -keystore <path_to_keystore>
Categories: Uncategorized Tags:

Maven 3, deploy file with scp

March 7th, 2014 No comments

By default maven 3 will only allow you to upload files by means of http.

This mean that deploying through scp will not work. My settings.xml contains the servers to which I want to upload through scp.

Settings.xml

<settings>
    <servers>
        <server>
            <id>sample-server-id</id>
            <username>myUsername</username>
            <password>myPassword</password>
        </server>
    </servers>
    <profiles>
	<profile>
            <id>default-profile</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
	    <repositories>
		<repository>
			<id>sample-server-id</id>
			<name>A sample repository</name>
			<url>scp://builds.example.org/maven</url>
		</repository>
	    </repositories>
	</profile>
    </profiles>
</settings>

Deploying the file with mvn deploy:deploy-file will give an error when using scp as the protocol.

mvn deploy:deploy-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.4 -DrepositoryId=sample-server-id -Dfile=ojdbc6.jar -Durl=scp://builds.example.org/maven
No connector available to access repository

To fix this we need to create a dummy pom.xml. The most important part is to add the ssh wagon to enable scp.

<project> 
	<modelVersion>4.0.0</modelVersion> 
	<groupId>com.oracle</groupId> 
	<artifactId>jdbc-driver</artifactId> 
	<version>11.2.0.4</version> 
	<build>
		<extensions>
			<extension>
				<groupId>org.apache.maven.wagon</groupId>
				<artifactId>wagon-ssh</artifactId>
				<version>2.6</version>
			</extension>
		</extensions>
	</build>
</project>

Now rerun the command:

mvn deploy:deploy-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.4 -DrepositoryId=sample-server-id -Dfile=ojdbc6.jar -Durl=scp://builds.example.org/maven

Hopefully it will now show:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Categories: Uncategorized Tags:

AngularJS Clearable Input Directive

March 2nd, 2014 No comments

I wanted a clearable input field. It is supposed to show a close icon when input is typed into the input field. It was inspired by the following discussion on stackoverflow.

It consists of three parts:

1) The image for the close icon. Just take any one you like. I used this one. cross
2) The required CSS.

.clearable {
    background: url(/images/icons/cross.png) no-repeat right 5px center;
}
 
.clearable.onX {
    cursor: pointer;
}

3) The required AngularJS directive

app.directive('clearable', function($parse) {
    var link = function link(scope, element, attrs) {
        element.on('click', function() {
            if (element.hasClass("onX")) {
                scope.$apply(function(scope) {
                    $parse(attrs.clearable).assign(scope, null);
                });
            }
        });
 
        scope.$watch(attrs.clearable, function(val) {
            //console.log("Value is now: " + val);
            if (val) {
                element
                    .addClass('clearable')
                    .on('mousemove.clearable', function(event) {
                        if (this.offsetWidth - 18 < event.clientX - this.getBoundingClientRect().left) {
                            element.addClass('onX');
                        } else {
                            element.removeClass('onX');
                        }
                    });
            } else {
                element
                    .removeClass('clearable')
                    .off('mousemove.clearable');
            }
        });
    };
 
    return {
        restrict: "A",
        replace: false,
        transclude: false,
        link: link
    };
});

Use it by adding the following attribute to an input element:

<input type="text" ng-model="valueToObserve" clearable="valueToObserve" />

It will look like this.
clearable_input

Categories: Uncategorized Tags:

Maven and Grails

January 27th, 2014 No comments

I needed to push the generated Grails war into a maven repository. There are several ways to do this. I used the grails create-pom command (2.3.1) to create a pom.xml file. This seemed most logical to me.

Then I tried to do a mvn clean install from there to have it put in my local repo. This failed hard.

Fatal error forking Grails JVM: java.lang.reflect.InvocationTargetException

I changed the grails-maven-plugin to not fork to get a less cryptic description of the problem.

<plugin>
	<groupId>org.grails</groupId>
	<artifactId>grails-maven-plugin</artifactId>
	<version>${grails.version}</version>
	<configuration>
		<!-- Whether for Fork a JVM to run Grails commands -->
		<fork>false</fork>
	</configuration>
	<extensions>true</extensions>
</plugin>

This got me the actual error description:

Unable to start Grails: java.lang.reflect.InvocationTargetException: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found

The dreaded xerces error.

I apparently had some unwanted dependencies. I executed a mvn dependency:tree to see if any of these were in use.
DynamicJasper seemed to be the culprit here. It contained a runtime dependency on xml-apis.

[INFO] +- ar.com.fdvs:DynamicJasper:jar:4.0.3:runtime
[INFO] |  \- net.sf.jasperreports:jasperreports:jar:4.1.1:runtime
[INFO] |     +- commons-digester:commons-digester:jar:1.7:runtime
[INFO] |     +- com.lowagie:itext:jar:2.1.7:runtime
[INFO] |     |  \- org.bouncycastle:bctsp-jdk14:jar:1.38:runtime
[INFO] |     |     +- org.bouncycastle:bcprov-jdk14:jar:1.38:runtime
[INFO] |     |     \- org.bouncycastle:bcmail-jdk14:jar:1.38:runtime
[INFO] |     +- jfree:jcommon:jar:1.0.15:runtime
[INFO] |     +- jfree:jfreechart:jar:1.0.12:runtime
[INFO] |     +- xml-apis:xml-apis:jar:1.3.02:runtime
[INFO] |     +- eclipse:jdtcore:jar:3.1.0:runtime
[INFO] |     +- org.codehaus.castor:castor:jar:1.2:runtime
[INFO] |     \- org.apache.poi:poi-ooxml:jar:3.6:runtime
[INFO] |        +- org.apache.poi:poi:jar:3.6:runtime
[INFO] |        \- org.apache.poi:poi-ooxml-schemas:jar:3.6:runtime
[INFO] |           +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:runtime
[INFO] |           \- org.apache.geronimo.specs:geronimo-stax-api_1.0_spec:jar:1.0:runtime

I then dropped the dependency in my pom.xml:

<dependency>
	<groupId>ar.com.fdvs</groupId>
	<artifactId>DynamicJasper</artifactId>
	<version>4.0.3</version>
	<scope>runtime</scope>
	<exclusions>
		<exclusion>
			<groupId>xml-apis</groupId>
			<artifactId>xml-apis</artifactId>
		</exclusion>
	</exclusions>
</dependency>

After this I could install/deploy the artifact.

Categories: Grails Tags:

Blank screen during install

November 30th, 2013 No comments

I had some problems while installing Ubuntu/Linux Mint on a laptop. The screen went blank.
After some investigation it turned out that the backlight was turned off. (Intel GMA 4500m chipset)
To fix this I found two options that worked (default brightness buttons on laptop were not working)

Add the following boot options:

acpi_osi=Linux

This option allows me to use the brightness controls on the laptop and thus restore the brightness to a viewable state.
If that doesn’t work you could also turn off i915. That will allow you to pass the setup at first. Maybe install an OpenSSH server and then go in to output a acceptable value into the backlight.

i915.modeset=0

After this I created a init.d script called backlight to set the backlight to a valid value at boot.

First I got the current value:

cat /sys/class/backlight/intel_backlight/actual_brightness
72250

Use that in the backlight script.

#!/bin/sh
echo 72250 > /sys/class/backlight/intel_backlight/brightness

This will probably only work when acpi_osi=Linux during boot. You can add that option to grub later on.
Edit (/etc/default/grub) add the rule to GRUB_CMDLINE_LINUX_DEFAULT, GRUB_CMDLINE_LINUX or GRUB_CMDLINE_DEFAULT and run update-grub2 afterwards.

Make it executable.

chmod +x backlight

Make it run at different runlevels.

update-rc.d backlight defaults 00

That should restore the backlight at some point during boot. Not an ideal solution, but at least a working one.

Categories: Linux, Ubuntu Tags: , , ,

JPA with UUID

June 12th, 2013 2 comments

I wanted to have a data package containing only JPA annotations.

I created a base class specifying the keytype (I use UUID and Long based Entities):

package com.famvdploeg.data;
 
import java.io.Serializable;
 
/**
 * Absolute base class for persistable classes.
 * Contract forces get and set methods for id.
 * @author wytze
 * @param <KeyType>
 */
public abstract class Persistable<KeyType extends Serializable> {
	public abstract KeyType getId();
 
	public abstract void setId(KeyType id);
}
package com.famvdploeg.data;
 
import java.util.UUID;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
 
@MappedSuperclass
public abstract class UuidBasedEntity extends Persistable<UUID> {
 
	@Id
	private UUID id;
 
	@Override
	public UUID getId() {
		return id;
	}
 
	@Override
	public void setId(UUID id) {
		this.id = id;
	}
}

Sample entity:

package com.famvdploeg.data;
 
import java.io.Serializable;
import java.util.UUID;
import javax.persistence.Entity;
 
@Entity
public class Sample extends UuidBasedEntity implements Serializable {
 
	private String someExampleProperty;
 
        /* ... getters and setters */
}

All these entities go in one separate jar.

Next I create another package using the entity jar.

package com.famvdploeg.dao;
 
import com.famvdploeg.data.Persistable;
import java.io.Serializable;
 
public interface GenericRepository<Entity extends Persistable> {
	public void persist(Entity e);
	public Entity findById(Serializable id);
	public void merge(Entity t);
	public void remove(Serializable id);
	public Entity saveOrUpdate(Entity entity);
}

And a generic implementation of this dao: (Spring is used to inject the persistencecontext)

package com.famvdploeg.dao.jpa;
 
import java.io.Serializable;
import com.famvdploeg.dao.GenericRepository;
import com.famvdploeg.data.Persistable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
 
public class GenericJpaRepository<Entity extends Persistable> implements GenericRepository<Entity> {
 
	@PersistenceContext
	protected EntityManager em;
 
	@Override
	public void persist(Entity e) {
		em.persist(e);
	}
 
	@Override
	public Entity findById(Serializable id) {
		return em.find(returnEntityClass(), id);
	}
 
	@Override
	public void merge(Entity e) {
		em.merge(e);
	}
 
	@Override
	public void remove(Serializable id) {
		em.remove(findById(id));
	}
 
	@Override
	public void flush() {
		em.flush();
	}
 
	@Override
	public Entity saveOrUpdate(Entity entity) {
		if (entity.getId() == null) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}
 
	protected List<Entity> findAll() {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
 
		return em.createQuery(cq).getResultList();
	}
 
	protected Entity findByProperty(String property, Object value) {
		try {
			return em.createQuery(createQueryByProperty(property, value)).getSingleResult();
		} catch (NoResultException ex) {
			return null;
		}
	}
 
	protected List<Entity> findAllByProperty(String property, Object value) {
		return em.createQuery(createQueryByProperty(property, value)).getResultList();
	}
 
	protected Entity findByProperties(Map<String, Object> properties) {
		try {
			return em.createQuery(createQueryByProperties(properties)).getSingleResult();
		} catch (NoResultException ex) {
			return null;
		}
	}
 
	protected List<Entity> findAllByProperties(Map<String, Object> properties) {
		return em.createQuery(createQueryByProperties(properties)).getResultList();
	}
 
	public Class<Entity> returnEntityClass() {
		ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
		return (Class<Entity>) genericSuperclass.getActualTypeArguments()[0];
	}
 
	private CriteriaQuery<Entity> createQueryByProperty(String property, Object value) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
		Root<Entity> root = cq.from(returnEntityClass());
		cq = cq.where(cb.equal(root.get(property), value));
		return cq;
	}
 
	private CriteriaQuery<Entity> createQueryByProperties(Map<String, Object> properties) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
		Root<Entity> root = cq.from(returnEntityClass());
		for (Entry<String, Object> entry : properties.entrySet()) {
			cq = cq.where(cb.equal(root.get(entry.getKey()), entry.getValue()));
		}
		return cq;
	}
}

Now I want to use hibernate to map my UUID’s as PostgreSQL uuid type. We will add a mapping to do so.

(location: com/famvdploeg/data/CustomTypes.hbm.xml, place in DAO/Repository jar)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!--
		http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/types.html
		Section 6.5 covers type registry and registerTypeOverride method on the Configuration object,
		typedefs are the preferred way of registering custom types
	-->
    <typedef name="java.util.UUID" class="org.hibernate.type.UUIDCharType" />
 
    <!-- 
        I want to store clob values as text and not as materialized clobs so we override that here.
        Otherwise the database will show long values when using an SQL tool to query the database.
    -->
    <typedef name="materialized_clob" class="org.hibernate.type.TextType" />
	<!-- Possible values:
	<typedef name="java.util.UUID" class="org.hibernate.type.UUIDBinaryTypee" />
	<typedef name="java.util.UUID" class="org.hibernate.type.UUIDCharType" />
	<typedef name="java.util.UUID" class="org.hibernate.type.PostgresUUIDType" />
	-->
</hibernate-mapping>

Next we fill the persistence.xml

(location: META-INF/persistence.xml)

<?xml version="1.0" encoding="UTF-8"?>
<persistence
	xmlns='http://java.sun.com/xml/ns/persistence'
	xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
	xsi:schemaLocation='http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd'
	version="2.0">
 
	<persistence-unit name="jpa-example-postgres" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
 
		<class>com.famvdploeg.data.Sample</class>
 
		<properties>
			<!--<property name="hibernate.archive.autodetection" value="class, hbm"/>-->
			<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
                        <!-- Use this only for testing!
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
                        -->
                        <!-- Nicer naming of tables with underscores fooName -> foo_name -->
			<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
 
			<!-- Connection properties, moved to datasource (@see applicationContext.xml)
			<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/jpa_example" />
			<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
			<property name="hibernate.connection.username" value="example" />
			<property name="hibernate.connection.password" value="example" />
			-->
 
			<!-- c3p0 connection pooling, setup when creating datasource (@see com.mchange.v2.c3p0.ComboPooledDataSource)
			<property name="hibernate.c3p0.min_size">5</property>
			<property name="hibernate.c3p0.max_size">20</property>
			<property name="hibernate.c3p0.timeout">300</property>
			<property name="hibernate.c3p0.max_statements">50</property>
			<property name="hibernate.c3p0.idle_test_period">3000</property>
			-->
		</properties>
 
                <!-- The specific mapping for UUID's is added here -->
		<mapping-file>com/famvdploeg/data/CustomTypes.hbm.xml</mapping-file>
	</persistence-unit>
</persistence>

And for completeness the applicationContext.xml for Spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
 
	xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       		http://www.springframework.org/schema/tx
       		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       		http://www.springframework.org/schema/aop
       		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
			http://www.springframework.org/schema/task
			http://www.springframework.org/schema/task/spring-task-3.0.xsd">
 
	<!-- In production: <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"> -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<!-- Test properties. Should be filled from Context.xml in production -->
		<property name="properties">
			<props>
				<!--
				<prop key="jpa-example-jdbc-url">jdbc:h2:mem:jpa_example</prop>
				<prop key="jpa-example-jdbc-username">sa</prop>
				<prop key="jpa-example-jdbc-password">sa</prop>
				<prop key="jpa-example-jdbc-driver">org.h2.Driver</prop>
				-->
				<prop key="jpa-example-jdbc-url">jdbc:postgresql://localhost:5432/jpa_example</prop>
				<prop key="jpa-example-jdbc-username">example</prop>
				<prop key="jpa-example-jdbc-password">example</prop>
				<prop key="jpa-example-jdbc-driver">org.postgresql.Driver</prop>
			</props>
		</property>
	</bean>
 
	<!-- Use pooled in production, @see com.mchange.v2.c3p0.ComboPooledDataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url" value="${jpa-example-jdbc-url}" />
		<property name="username" value="${jpa-example-jdbc-username}" />
		<property name="password" value="${jpa-example-jdbc-password}" />
		<property name="driverClassName" value="${jpa-example-jdbc-driver}" />
	</bean>
 
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="jpa-example-postgres" />
		<property name="dataSource" ref="dataSource" />
	</bean>
 
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
 
	<tx:annotation-driven transaction-manager="transactionManager" />
 
	<context:annotation-config />
</beans>

It is also possible to store the UUID as a char(36) to do this we need to change the type in the CustomTypes.hbm.xml to org.hibernate.type.UUIDCharType.
We can then modify the mapping from the data jar through adding an orm.xml to the META-INF folder. It will normally create a varchar(255) column but that is useless. We want to specify the use of an char(36) column as UUID’s are stored as Strings of a fixed length of 36 characters.

<?xml version="1.0" encoding="UTF-8"?>
 
<entity-mappings
  xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
  version="2.0">
 
	<package>com.famvdploeg.data</package>
 
	<mapped-superclass class="UuidBasedEntity" metadata-complete="false">
		<attributes>
			<id name="id">
				<column column-definition="char(36)" />
			</id>
		</attributes>
	</mapped-superclass>
</entity-mappings>

That’s it! Awesome! Clean separation of JPA and Hibernate.

Categories: Java Tags:

Grails easy JSON DTO’s

May 25th, 2013 No comments

Some JSON is only used in specific places. For these occurrences I use extension methods / meta methods to easily convert my classes into the required JSON without the need for a specific mapping/dto class. To do this I declare a Markup interface (called Mappable) on which the method can be invoked.

I put the following interface in src/groovy:

package com.example.json
 
/**
 * Markup interface so we can add extension methods to convert objects to maps.
 * @see MetaMethods.groovy
 */
interface Mappable {}

I then add the following to my MetaMethods class in src/groovy:

package com.example.json;
 
class MetaMethods {
    static void register() {
        Mappable.metaClass.toMap { whitelist, blacklist ->
            /* metaClass, class */
            def map = [:];
 
            /* id seems to be a special case */
            if (("id" in whitelist) || (!"id" in blacklist)) {
                map["id"] = delegate["id"];
            }
 
            if (whitelist) {
                whitelist.each {
                    map[it] = delegate[it]
                }
            } else if (blacklist) {
                delegate.properties.each { prop, val ->
                    if (!(prop in blacklist)) {
                        map[prop] = val;
                    }
                }
            }
            return map;
        }
    }
}

I register the metamethods in my Bootstrap.groovy

class BootStrap {
    def init = { servletContext ->
 
        /* Register our own Meta Methods/Extension Methods */
        MetaMethods.register();
    }
}

Now we can create easy JSON dto’s based on our domain (don’t forget to add the Mappable interface to your domain classes).

Usage example:

        def jsonMap = myDomainClass.toMap(["id", "propertyX", "propertyZ"], []); // 1st level properties
        jsonMap["customer"] = myDomainClass.customer ? myDomainClass.customer.toMap(["id", "fullName", "firstName", "insertion", "lastName"], []) : null; // 2nd level properties
        render jsonMap as JSON; // or as XML

Happy Grailing!

Setting up an OrientDB server on Ubuntu

January 19th, 2013 13 comments

Go to the directory you want to install OrientDB.

cd /opt

Download one of the two flavors of OrientDB (standard or graph edition). (If you don’t know which to take, pick the Graph Ed.)

sudo wget https://s3.amazonaws.com/orientdb/releases/orientdb-1.3.0.tar.gz
#sudo wget https://s3.amazonaws.com/orientdb/releases/orientdb-graphed-1.3.0.tar.gz

Unpack the file

sudo tar -zxvf orientdb-1.3.0.tar.gz

I usually remove the tar.gz file and add a symlink

sudo rm orientdb-1.3.0.tar.gz
sudo ln -s orientdb-1.3.0/ orientdb

Configure the default orientdb password. (I use vi, you use your own favorite editor ;))

sudo vi orientdb/config/orientdb-server-config.xml

Go to the section [orient-server > storages > storage] in the xml, change the default username and password and save the file

<!-- Default in-memory storage. Data are not saved permanently. -->
<storage path="memory:temp" name="temp" userName="yourUsername" userPassword="yourPassword" loaded-at-startup="true" />

Get the root password for later use or/and add your own preferred account in [orient-server > users]:
(I prefer to remove the root account and add a new one)

<user name="yourUsername" password="yourPassword" resources="*"/>

As the file is holding passwords it might be a good idea to remove the read permission for other users.

sudo chmod 640 /opt/orientdb/config/orientdb-server-config.xml

Create a user that will run the server:

# -d, --home-dir HOME_DIR       home directory of the new account
# -M, --no-create-home          do not create the user's home directory
# -r, --system                  create a system account
# -s, --shell SHELL             login shell of the new account (/bin/false =  no login)
# -U, --user-group              create a group with the same name as the user
sudo useradd -d /opt/orientdb -M -r -s /bin/false -U orientdb

Change ownership of orientdb directory/links:

sudo chown -R orientdb.orientdb orientdb*

Modify the user group rights so that users in the orientdb group can invoke shell scripts.

sudo chmod 775 /opt/orientdb/bin
sudo chmod g+x /opt/orientdb/bin/*.sh
sudo usermod -a -G orientdb yourUsername

Copy the init.d script:

sudo cp orientdb/bin/orientdb.sh /etc/init.d/

Update the init.d script with this sed script or just edit the file. (The copied one)

sudo sed -i "s|YOUR_ORIENTDB_INSTALLATION_PATH|/opt/orientdb|;s|USER_YOU_WANT_ORIENTDB_RUN_WITH|orientdb|" /etc/init.d/orientdb.sh

And change the following lines, we use sudo because our system account does not have a login shell.

# You have to SET the OrientDB installation directory here (if not already done so)
ORIENTDB_DIR="/opt/orientdb"
ORIENTDB_USER="orientdb"
 
#su -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./server.sh 1>../log/orientdb.log 2>../log/orientdb.err &" - $ORIENTDB_USER
sudo -u $ORIENTDB_USER sh -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./server.sh 1>../log/orientdb.log 2>../log/orientdb.err &"
 
#su -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./shutdown.sh 1>>../log/orientdb.log 2>>../log/orientdb.err &" - $ORIENTDB_USER
sudo -u $ORIENTDB_USER sh -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./shutdown.sh 1>>../log/orientdb.log 2>>../log/orientdb.err &"

Update the rc.d dirs

cd /etc/init.d
sudo update-rc.d orientdb.sh defaults

The server will now start and stop on startup/shutdown. For now we start it by hand.

sudo /etc/init.d/orientdb.sh start

Verify that it is running by opening the studio (e.g. http://localhost:2480/) or run ‘sudo /etc/init.d/orientdb.sh status’.

Now we can log in and create a new database,
Start the console:

/opt/orientdb/bin/console.sh

Create a new database:

create database remote:/yourDatabaseName yourUsername yourPassword local

Done. Grab a beer, you’ve earned it. 😉