In the tutorial below I will focus on transactions management with Spring 3. For the sake of simplicity, we will create a standalone Java application – but the same logic can be used in J2EE application. We will create:

  • Entity objects (simple POJO) – the basic entities mapped to the relational database (via annotations).
  • DAO objects handling database (Hibernate) queries.
  • Business Object that will expose services around our data.
  • Main application to simply run our code. This is what will probably need to be replaced with your web application logic, if you are creating one.

Our application will be very simple – two main tables/objects: User and Email, with the many-to-many relationship between them. Let’s start with the SQL to create and populate database. I’m using MySQL but it should work on any other DB with the minimal changes:

CREATE TABLE IF NOT EXISTS `email` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `address` VARCHAR(250) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `email` (`id`, `address`) VALUES
(1, 'a1@opensesam.net'),
(2, 'a2@opensesam.net');
 
CREATE TABLE IF NOT EXISTS `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `age` INT(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `user` (`id`, `age`) VALUES (1, 34), (2, 19);
 
CREATE TABLE IF NOT EXISTS `user_email` (
  `user_id` INT(11) NOT NULL,
  `email_id` INT(11) NOT NULL,
  KEY `user_id` (`user_id`),
  KEY `email_id` (`email_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `user_email` (`user_id`, `email_id`) VALUES (1, 1), (1, 2);
 
ALTER TABLE `user_email`
  ADD CONSTRAINT `user_email_ibfk_2` FOREIGN KEY (`email_id`) REFERENCES `email` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  ADD CONSTRAINT `user_email_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;

Next, our entity objects. You can download a full source code, so I’m displaying here only the relevant parts of the code. Entity objects are simple POJOs but they contain annotations for Hibernate:

package net.opensesam.entity;
 
import javax.persistence.*;
 
@Entity
@Table(name = "user")
public class User {
 
	@Id
	private int id;
 
	@Column(name = "age")
	private int age;
 
	@ManyToMany
	@JoinTable(name = "user_email", 
			joinColumns = { @JoinColumn(name = "user_id") },
			inverseJoinColumns = {@JoinColumn(name = "email_id")} )
	private Set<Email> emails = new HashSet<Email>();
//the rest are just setters and getters
@Entity
@Table(name = "email")
public class Email {
 
	@Id
	private int id;
 
	@Column(name = "address")
	private String address;
 
	@ManyToMany(mappedBy = "emails")
	private Set<User> users = new HashSet<User>();
//...

Our DAO objects will need a reference to SessionFactory – we will use a constructor to pass that object and let Spring do the job. Let’s define a getFirstEmail method in UserDao – suppose this is for finding only one, primary email for a user.

public class UserDao extends AbstractDao<User> {
	public UserDao(SessionFactory sessionFactory) {
		super(User.class, sessionFactory);
	}
 
	public Email getFirstEmail(int userId) {
		Email email = (Email) query(
				"select email from Email email join email.users u where u.id = ?")
				.setInteger(0, userId).setMaxResults(1).uniqueResult();
 
		return email;
	}
}

EmailDao is not even worth showing here – it simply extends AbstractDao. Now, our business logic finally. We will be coding to an interface, so we’ll create interface net.opensesam.bo.UserBo:

package net.opensesam.bo;
 
import net.opensesam.entity.*;
 
public interface UserBo {
 
  User findById(int id);
 
  void insert(User user);
 
  void complexTransaction(User user);
 
  Email getPrimaryEmail(User user);
 
}

The methods are implemented by UserBoImpl. All of them are used from the Main class, so you can refer to the source code – let’s have a look at only one of them – public void complexTransaction(User user). This is to emulate a few-steps transaction:

public void complexTransaction(User user) {
		User u = findById(user.getId());
		// update all user's email addresses
		for (Email e : u.getEmails()) {
			e.setAddress(e.getAddress() + ".new");
		}
		/* If exception is thrown, no changes should be persisted in DB
		if (true) {
			throw new RuntimeException("Ouch, an exception!");
		}
		*/
		// update user's age
		u.setAge(u.getAge() + 100);
	}

If an exception is run in the middle of the method, Spring should rollback the transaction. Otherwise, the whole complexTransaction method should execute as one transaction.
All the magic happens in Spring configuration – beans.xml in my case:

<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
 
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*" />
		</tx:attributes>
	</tx:advice>
 
	<aop:config>
		<aop:advisor advice-ref="txAdvice"
			pointcut="execution(* net.opensesam.bo.*.*(..))" />
	</aop:config>

We need to define transactionManager that will understand the persistence technology we are using – hence HibernateTransactionManager in this case. Transaction manager obviously needs a reference to SessionFactory. Every time our transactional method is run, Transaction Manager has to run as well and do all the work for us, like: opening connection if needed, starting transaction, rolling back / committing. This means we need some kind of proxy object, or a wrapper around UserBoImpl class. AOP comes in very handy here, as we can have that done declaratively, without any changes to the source code. First we define when our transaction management code should run by setting pointcut=”execution(* net.opensesam.bo..(..))”. You may want to refer to Spring AOP tutorial for the very basics of AOP. Next, we define our advice (what should run) txAdvice that refers to the transaction manager we use. tx:attributes element contains additional information like: which methods should be transactional, which of them can be declared as read-only for possible optimizations and under what conditions should rollback be triggered. By default any unchecked exception will trigger rollback. The example above is very simple, basically any method from any class from net.opensesam.bo package will be treated as transactional.

The above works as expected – here is what I can see in MySQL log, when the exception is not thrown:

		  807 Query	SET autocommit=0
		  807 Query	/* load net.opensesam.entity.User */ select user0_.id as id0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=1
		  807 Query	/* load collection net.opensesam.entity.User.emails */ select emails0_.user_id as user1_0_1_, emails0_.email_id as email2_1_, email1_.id as id1_0_, email1_.address as address1_0_ from user_email emails0_ inner join email email1_ on emails0_.email_id=email1_.id where emails0_.user_id=1
		  807 Query	/* update net.opensesam.entity.User */ update user set age=234 where id=1
		  807 Query	/* update net.opensesam.entity.Email */ update email set address='a1@opensesam.net.new.new' where id=1
		  807 Query	/* update net.opensesam.entity.Email */ update email set address='a2@opensesam.net.new.new' where id=2
		  807 Query	commit

Compare it with what happens if when the exception is thrown:

		  812 Query	SET autocommit=0
		  812 Query	/* load net.opensesam.entity.User */ select user0_.id as id0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=1
		  812 Query	/* load collection net.opensesam.entity.User.emails */ select emails0_.user_id as user1_0_1_, emails0_.email_id as email2_1_, email1_.id as id1_0_, email1_.address as address1_0_ from user_email emails0_ inner join email email1_ on emails0_.email_id=email1_.id where emails0_.user_id=1
		  812 Query	rollback

The list of jar files used while working on the code:

  • org.springframework.context-3.0.5.RELEASE.jar
  • org.springframework.beans-3.0.5.RELEASE.jar
  • org.springframework.orm-3.0.5.RELEASE.jar
  • org.springframework.transaction-3.0.5.RELEASE.jar
  • hibernate3.jar
  • hibernate-jpa-2.0-api-1.0.0.Final.jar
  • org.springframework.core-3.0.5.RELEASE.jar
  • commons-logging-1.1.1.jar
  • org.springframework.asm-3.0.5.RELEASE.jar
  • aopalliance-1.0.jar
  • org.springframework.aop-3.0.5.RELEASE.jar
  • org.springframework.expression-3.0.5.RELEASE.jar
  • org.springframework.jdbc-3.0.5.RELEASE.jar
  • aspectjweaver-1.6.6.jar
  • mysql-connector-java-5.1.13.jar
  • jta-1.1.jar
  • dom4j-1.6.1.jar
  • slf4j-log4j12-1.6.1.jar
  • slf4j-api-1.6.1.jar
  • log4j-1.2.16.jar
  • commons-collections-3.2.1.jar
  • javassist-3.8.0.GA.jar
  • antlr-2.7.7.jar

Spring Transactions AOP – source code


Simple Spring

In this tutorial we will create, from the very beginning, a simple application that uses Spring and its Aspect Oriented Programming capabilities. We will use schema-based approach from Spring 2.0 to define the AOP configuration.
I am not going to cover here the AOP or Spring basis, if you are interested what AOP is or why would you use it, try documentation on Spring or AspectJ website.

Let’s create a very simple class – we will base all the examples on it:

package techblog.zabuchy.net;
 
public class Person
{
	private String name;
	private String website;
 
	public void setName(String name) {
		this.name = name;
	}
 
	public void setWebsite(String website) {
		this.website = website;
	}
 
	public void printName(){
		System.out.println("My name: " + this.name);
	}
 
	public void printWebsite(){
		System.out.println("My website: " + this.website);
		privateMethod();
                publicMethod();
	}
 
	private void privateMethod() {
		System.out.println("Private method");
	}
 
	private void publicMethod() {
		System.out.println("Public method");
	}
	public void throwException(){
		throw new IllegalArgumentException();
	}
}

We also need a main class that we’ll be running – again, very simple one will be enough:

package techblog.zabuchy.net;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class App {
	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "spring.xml" });
 
		Person me = (Person) appContext.getBean("person");
 
		System.out.println("About to print a name...");
		me.printName();
 
		System.out.println("About to print a website...");
		me.printWebsite();
 
		System.out.println("About to throw an exception...");
		try {
			me.throwException();
		} catch (Exception e) {
 
		}
	}
}

Our spring.xml contains a definition of person bean:

<bean id="person" class="techblog.zabuchy.net.Person">
		<property name="name" value="Tomasz Muras" />
		<property name="website" value="http://techblog.zabuchy.net" />
	</bean>

Aspect Oriented Programming with Spring

It’s all nice & easy so far – but let’s add AOP to that mix. We basically need two things:

  • We need the functionality/feature/concern that needs to run across different classes – using proper terminology we need our aspect.
  • We need to tell (advice) Spring when this aspect should run. The first bit is very simple – aspect can simply be a class with a method:
package techblog.zabuchy.net;
 
public class InjectMe {
	public void injectMethod() {
		System.out.println("INJECT!");
	}
}

The second bit will be defined declaratively in our spring.xml. First we need our “aspect class” as a normal bean:

<bean id="inject" class="techblog.zabuchy.net.InjectMe" />

Then we declare AOP behavior – all is wrapped in <aop:config> tag (I’ll cover aop namespace shortly). We need to refer to our inject bean:

<aop:config>
<aop:aspect ref="inject">
...
</aop:aspect>
</aop:config>

Then we need to say when it should run. The when in Spring is simple – it always refers to some method execution. In our example, we would like to run our InjectMe class when any method from Person is executed – in AOP terminology it means we need to define a pointcut that refers to all those methods:

<aop:config>
<aop:aspect ref="inject">
<aop:pointcut expression="execution(* techblog.zabuchy.net.Person.*(..))" id="pointcut1" />
....
</aop:aspect>
</aop:config>

The pointcut simply points to the methods, we need to specify when exactly aspect should run (before the method executes or maybe after?). We also need to say which method of our inject bean is to be executed:

<aop:config>
<aop:aspect ref="inject">
<aop:pointcut expression="execution(* techblog.zabuchy.net.Person.*(..))" id="pointcut1" />
<aop:before method="injectMethod" pointcut-ref="pointcut1" />
</aop:aspect>
</aop:config>

That’s it! When we run the example, the output will look like below:

About to print a name...
INJECT!
My name: Tomasz Muras
About to print a website...
INJECT!
My website: http://techblog.zabuchy.net
Private method
Public method
About to throw an exception...
INJECT!

Notice that the aspect was run 3 times – and we have run 3 public methods on an object of Person class. When object executes its own method, AOP did not work. To complete Spring’s XML file, we need to add aop namespace and schema. The full spring.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
	<bean id="inject" class="techblog.zabuchy.net.InjectMe" />
 
	<bean id="person" class="techblog.zabuchy.net.Person">
		<property name="name" value="Tomasz Muras" />
		<property name="website" value="http://techblog.zabuchy.net" />
	</bean>
 
	<aop:config>
		<aop:aspect ref="inject">
			<aop:pointcut expression="execution(* techblog.zabuchy.net.Person.*(..))"
				id="pointcut1" />
			<aop:before method="injectMethod" pointcut-ref="pointcut1" />
		</aop:aspect>
	</aop:config>
</beans>

Run after returning from a method

If we would like to execute the aspect after the method is run, we replace element with . Since the method executed already, we can also get hold of the return value. To do so, we’ll declare our aspect method with an extra argument:

public class InjectMe {
	public void injectAfter(Object ret) {
		System.out.println("INJECT AFTER! Returned: " + ret);
	}
}

Updated XML file:

<aop:config>
		<aop:aspect ref="inject">
			<aop:pointcut expression="execution(* techblog.zabuchy.net.Person.*(..))"
				id="pointcut1" />
			<aop:after-returning returning="ret" method="injectAfter" pointcut-ref="pointcut1" />
		</aop:aspect>
	</aop:config>

And the output this time. Note that the aspect did not execute after a method has thrown an exception.

About to print a name...
My name: Tomasz Muras
INJECT AFTER! Returned: null
About to print a website...
My website: http://techblog.zabuchy.net
Private method
Public method
INJECT AFTER! Returned: null
About to throw an exception...

Run after an exception is thrown and run always (finally)

You can also run aspect only after a method throws an exception with <aop:after-throwing> element or in both cases using <aop:after>. You will find the examples of both in the attached source code.

Run before and after the exception

The most powerful advice is <aop:around>. It runs both before and after method execution and it gives you the opportunity to cancel method execution altogether.
The schema definition looks just like for previous advices:

	<aop:config>
		<aop:aspect ref="inject">
			<aop:pointcut expression="execution(* techblog.zabuchy.net.Person.*(..))"
				id="pointcut1" />
			<aop:around method="injectAround" pointcut-ref="pointcut1" />
		</aop:aspect>
	</aop:config>

Advice method must have the first argument of type org.aspectj.lang.ProceedingJoinPoint. When/if we decide to run the actual method, we run proceed() method on the ProceedingJoinPoint object.

	public Object injectAround(ProceedingJoinPoint pjp) throws Throwable {
		// do some logic before
		System.out.println("INJECT BEFORE!");
 
		// run the actual method
		Object retVal = null;
		try {
			retVal = pjp.proceed();
		} catch (Exception e) {
 
		}
 
		// more logic after method executes
		System.out.println("INJECT AFTER!");
		return retVal;
	}

Source code and dependencies

You can download full source code with all the examples above. Here is a list of jars I’ve used for compiling the example:

  • spring-aop-3.0.4.RELEASE.jar
  • spring-beans-3.0.4.RELEASE.jar
  • spring-context-3.0.4.RELEASE.jar
  • spring-core-3.0.4.RELEASE.jar
  • spring-expression-3.0.4.RELEASE.jar
  • spring-test-3.0.4.RELEASE.jar
  • spring-tx-3.0.4.RELEASE.jar
  • spring-asm-3.0.4.RELEASE.jar
  • commons-logging-1.1.1.jar
  • aopalliance-1.0.jar
  • cglib-2.2.jar
  • asm-3.1.jar
  • spectjrt.jar
  • aspectjtools.jar
  • org.aspectj.matcher.jar
  • log4j-1.2.16.jar

This is part 4 of the Java Technologies Integration tutorial

Execution

The final part of your development is to execute our project and see fruits of our hard work. To run our project we have to build war file/directory and deploy it on Tomcat server.

War file/directory

Building war file/directory is always the same. In order to do it run the following commands:

mvn clean
mvn compile
mvn war:war

This combination ensures that previous compilations are cleaned and only the outcome of the newest compilation is placed in war file/directory. Keep in mind that ‘mvn war:war’ does not compile project sources. Final content of target as well as war directory is presented in Figure 13.

Final_content

Deployment to Tomcat server

There is a number of ways to deploy it to Tomcat server.

  • You can just copy content of target/IntegrationProject-1.0/ to webapps/IntegrationProject/ directory in Tomcat and start the server. Start Tomcat server.
  • You can make symlink webapps/IntegrationProject/ to point to target/IntegrationProject-1.0/. You should restart Tomcat when content of war file directory changes.
  • You can make symlink in WebContent to point to target/IntegrationProject-1.0/. Then add it to Tomcat server previously configured in Ecplise as shown in Figure 14. Start the server. After each project refresh if java classes changed the server will restart. If you did the change to xml files you might have to restart the server manually.

ecplise_tomcat_deployment

Final result

To see the final result go to ‘http://localhost:8080/IntegrationProject/listAllUsers.action’. This action should list all the users in the database and provide a link to add new one. Click on ‘Add’. This should invoke ‘http://localhost:8080/IntegrationProject/addUserForm.action’ as presented in Figure 15.

add_user_form

Fill in the form and click ‘Submit’. This should invoke ‘addUser.action’, which adds user to the database and redirect the request to listAllUsers.action as presented in Figure 16.

list_all_action

When you click delete the following action deleteUser.action with parameter id=id of user to be deleted will be issues and the user will be deleted from the database.

Updates to the project can be found in part 5 of the tutorial, which can be found here: Java Technologies Integration tutorial – part 5 – Hibernate update


This is part 3 of the Java Technologies Integration tutorial.

Sping Beans

Having user entity create it is finally the time to write some code! We are going to create two Spring Beans: Bussiness Object (BO) to providing interface for bussiness operations and Data Access Object (DAO) to communicate with database using entity User. To do so, we create two interfaces (UserBo and UserDao) and their implementations (UserBoImpl and UserDaoImpl) in package com.frogdroid.integration.user. The content of the files is listed below.

UserBo.java

package com.frogdroid.integration.user;
 
import java.util.List;
 
import com.frogdroid.integration.user.entity.User;
 
public interface UserBo {
 
    void add(User user);
 
    void update(User user);
 
    void delete(User user);
 
    List findAll();
 
    List findById(int id);
 
    List findByUsername(String username);
}

UserBoImpl.java

package com.frogdroid.integration.user;
 
import java.util.List;
 
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
 
import com.frogdroid.integration.user.entity.User;
 
@Transactional
public class UserBoImpl implements UserBo {
 
    private static final Logger LOGGER = Logger.getLogger(UserBoImpl.class.getName());
 
    @Autowired
    private UserDao userDao;
 
    public UserDao getUserDao() {
        return userDao;
    }
 
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
 
    public void add(User user) {
        if (user == null) {
            return;
        }
        LOGGER.debug("Adding the following user: " + user.getUsername() + ", " + user.getPassword());
        userDao.add(user);
    }
 
    public void delete(User user) {
        if (user == null) {
            return;
        }
        LOGGER.debug("Deleteting the following user: " + user.getId() + ", " + user.getUsername() + ", " + user.getPassword());
        userDao.delete(user);
    }
 
    public List findAll() {
        LOGGER.debug("Getting all users");
        return userDao.findAll();
    }
 
    public List findById(int id) {
        return userDao.findById(id);
    }
 
    public List findByUsername(String username) {
        return userDao.findByUsername(username);
    }
 
    public void update(User user) {
        if (user == null) {
            return;
        }
        userDao.update(user);
    }
}

UserDao.java

package com.frogdroid.integration.user;
 
import java.util.List;
 
import com.frogdroid.integration.user.entity.User;
 
public interface UserDao {
 
    void add(User user);
 
    void update(User user);
 
    void delete(User user);
 
    List findAll();
 
    List findById(int id);
 
    List findByUsername(String username);
}

UserDaoImpl.java

package com.frogdroid.integration.user;
 
import java.util.List;
 
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
 
import com.frogdroid.integration.user.entity.User;
 
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
 
    public void add(User user) {
        getHibernateTemplate().save(user);
    }
 
    public void delete(User user) {
        getHibernateTemplate().delete(user);
    }
 
    public List findAll() {
        return getHibernateTemplate().find("from User");
    }
 
    public List findById(int id) {
        return getHibernateTemplate().find("from User where id=?", id);
    }
 
    public List findByUsername(String username) {
        return getHibernateTemplate().find("from User where username=?", username);
    }
 
    public void update(User user) {
        getHibernateTemplate().update(user);
    }
}

Following that we create appropriate bean definitions and put them in src/main/resources/resources/spring/UserBean.xml file.

UserBean.xml

<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<bean id="userBo" class="com.frogdroid.integration.user.UserBoImpl">
		<property name="userDao" ref="userDao" />
	</bean>
 
	<bean id="userDao" class="com.frogdroid.integration.user.UserDaoImpl">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
 
</beans>

In addition we include UserBean.xml file in src/main/webapp/WEB-INF/applicationContext.xml file as follows:

<!-- Beans Declaration -->
<import resource="classes/resources/spring/UserBean.xml" />

Structure of the project after changes is presented in Figure 10.

bo_dao_configuration

Integration with Struts2

To use Struts2 in our project we have to add filter to web.xml file. The filter will be mapped, so each request to *.action and struts/* will be executed through StrutsPrepareAndExecuteFilter. The part to be added to web-app section in web.xml is presented below.

<filter>
	<filter-name>struts2</filter-name>
	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
 
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>*.action</url-pattern>
</filter-mapping>
 
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>/struts/*</url-pattern>
</filter-mapping>

Following that we have to create UserAction class that runs appropriate actions and return input to StrutsPrepareAndExecuteFilter. The class is put in src/main/java/com/frogdroid/integration/user/action/UserAction.java and its content is listed below.

UserAction.java

package com.frogdroid.integration.user.action;
 
import java.util.List;
 
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
 
import com.frogdroid.integration.user.UserBo;
import com.frogdroid.integration.user.entity.User;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.Preparable;
 
public class UserAction implements Preparable {
 
    private static final Logger LOGGER = Logger.getLogger(UserAction.class.getName());
 
    private List users;
 
    private Integer id;
    private String username;
    private String password;
 
    @Autowired
    private UserBo userBo;
 
    public UserBo getUserBo() {
        return userBo;
    }
 
    public void setUserBo(UserBo userBo) {
        this.userBo = userBo;
    }
 
    public List getUsers() {
        return users;
    }
 
    public void setUsers(List users) {
        this.users = users;
    }
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String listAll() {
        if (userBo == null) {
            return Action.ERROR;
        }
        LOGGER.debug("Get all users");
        users = userBo.findAll();
        LOGGER.debug("Users number = " + users.size());
        return Action.SUCCESS;
    }
 
    public String delete() {
        if (userBo == null) {
            return Action.ERROR;
        }
 
        User user = getUser(id);
        if (user == null) {
            return Action.ERROR;
        }
 
        LOGGER.debug("Delete user " + user.getUsername() + " with id " + user.getId());
        userBo.delete(user);
        return Action.SUCCESS;
    }
 
    public String add() {
        if (userBo == null) {
            return Action.ERROR;
        }
 
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        LOGGER.debug("Add user: " + user.getUsername());
        userBo.add(user);
        return Action.SUCCESS;
    }
 
    public String execute() {
        return Action.SUCCESS;
    }
 
    public void prepare() throws Exception {
 
    }
 
    private User getUser(Integer id) {
        LOGGER.debug("Get user with id = " + id);
        if (id != null) {
            List users = userBo.findById(id);
            LOGGER.debug("Number of users with id = " + id + ": " + users.size());
            if (users.size() == 1) {
                return (User) users.get(0);
            }
        }
        return null;
    }
}

We add the following action bean definition to UserBean.xml file, so it can be used in struts action file.

<bean id="userAction" class="com.frogdroid.integration.user.action.UserAction">
	<property name="userBo" ref="userBo" />
</bean>

Following that we have to create file with struts actions. The file should be placed in WEB-INF/classes/struts.xml in final war structure, which indicates that it should be created in src/main/resources/struts.xml. If you use different location struts actions will not be mapped. The file mapps actions invoked by the user to appropriate java classes/beans and its content is presented below. Depending on action appropriate methods (listAll, delete, add) from UserAction class are invoked. Our application has the functionality to list, add, and delete users from database.

struts.xml

<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
     "http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>
 
	<constant name="struts.devMode" value="true" />
 
	<package name="default" extends="struts-default">
 
		<action name="listAllUsers" method="listAll" class="userAction">
			<result name="success">WEB-INF/content/user/list.jsp</result>
		</action>
 
		<action name="deleteUser" method="delete" class="userAction">
			<result type="redirect">listAllUsers.action</result>
		</action>
 
		<action name="addUserForm" class="userAction">
			<result>WEB-INF/content/user/addForm.jsp</result>
		</action>
 
		<action name="addUser" method="add" class="userAction">
			<result type="redirect">listAllUsers.action</result>
		</action>
 
	</package>
</struts>

To show add user form we have to create WEB-INF/content/user/addForm.jsp file and to list all users we have to create WEB-INF/content/user/list.jsp. The content of the files is presented below.

addForm.jsp

<%@ taglib prefix="s" uri="/struts-tags"%>
 
<html>
<head>
<title>Add User</title>
</head>
<body>
 
<p>Add User</p>
 
<s:form name="addForm" method="post" action="addUser.action">
 
	<s:textfield name="username" label="User" />
	<s:password name="password" label="Password" />
 
	<s:submit type="button" name="Add" />
 
</s:form>
 
</body>
</html>

Make sure that the names of the fields correspond to properties in your UserAction class.

list.jsp

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sx" uri="/struts-dojo-tags"%>
 
<html>
<head>
<title>User List</title>
<sx:head debug="true" cache="false" compressed="false" />
</head>
<body>
 
<p>User List</p>
<div><s:url id="addUser" value="addUserForm.action">
</s:url><s:a href="%{addUser}">Add</s:a></div>
<s:if test="users.size > 0">
	<table id="users">
		<s:iterator value="users">
			<tr>
				<td><s:property value="username" /></td>
				<td><s:property value="password" /></td>
				<td><s:url id="deleteUser" value="deleteUser.action">
					<s:param name="id" value="id" />
				</s:url> <s:a href="%{deleteUser}">Delete</s:a></td>
			</tr>
		</s:iterator>
	</table>
</s:if>
 
</body>
</html>

Make sure that the names of the properties correspond to properties in your User entity. In addition, iterator uses property (‘users’) that should be defined in UserAction class.

The structure of the project after changes is presented in Figure 11.

struts2_structure

Final struture

Before showing final project structure let’s tidy a little bit up. Remove:

  • Remove class: App.java
  • Remove class: AppTest.java
  • Change Default output folder (Java build path -> Source) to IntegrationProject/target/classes
  • Remove folder: build

Having all that done the final structure of the project should look as presented in Figure 12.

final_structure

Test that all is OK so far:

mvn clean
mvn compile
mvn war:war

Part 4 of the tutorial can be found at Java Technologies Integration tutorial – part 4.


This is part 2 of the Java Technologies Integration tutorial.

Integration with Spring and Hibernate

In order to integrate the project with Spring and Hibernate a number of the files presented in Figure 5 have to be created. The content of the files is presented in the following part of this section.

integration_spring_hibernate_file_structure

database.properties

This file includes information used to connect to database. We use MySQL database to store our data. Make sure that jdbc.url, jdbc.username, and jdbc.password are updated with your settings.

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://<strong>127.0.0.1:3306/IntegrationProject</strong>
jdbc.username=<strong>integrationProjectUser</strong>
jdbc.password=<strong>integrationProjectPassword</strong>

log4j.properties

This file includes information used to log the data. For more information refer to log4j. Again, replace bold values with the correct settings.

### direct log messages to stdout ###
log4j.rootLogger=ERROR, console, file

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.SimpleLayout

# AdminFileAppender - used to log messages in the admin.log file.
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=<strong>path_to_your_log_directory</strong>/IntegrationProject.log
log4j.appender.file.layout=org.apache.log4j.SimpleLayout

log4j.logger.com.frogdroid=DEBUG, console, file

DataSource.xml

Spring Bean defined to connect to database.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location">
			<value>WEB-INF/classes/resources/database/database.properties</value>
		</property>
	</bean>
 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
 
</beans>

Hibernate.xml

Spring Bean defined to create session factory for hibernate.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<!-- Hibernate session factory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
 
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
 
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
 
		<property name="mappingResources">
			<list />
		</property>
 
	</bean>
</beans>

applicationContext.xml

This file is used by Spring to create appropriate Spring Beans. For convenience it includes imports of appropriate files with Spring Beans. applicationContext.xml is default name and can be changed in web.xml file.

<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<!-- Database Configuration -->
	<import resource="classes/resources/spring/config/DataSource.xml" />
	<import resource="classes/resources/spring/config/Hibernate.xml" />
 
</beans>

Updates to web.xml

In order to enable the integration the following changes should be done to web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
	<display-name>IntegrationProject</display-name>
 
	<!-- Spring beans -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml </param-value>
	</context-param>
 
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/classes/resources/logs/log4j.properties</param-value>
	</context-param>
 
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
 
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
 
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
 
</web-app>

Entities

To communicate with database using Hibernate we have to create entities, which are layer between database and business interface of our application. The most convenient way to do that in Eclipse is to add MySQL database to data sources and create entity directly from the table. In order to do so, select:

File -> New -> Connection Profiles -> Connection Profile
Select: MySQL
Enter data as shown in Figure 6.

mysql_connection_ecplise

After clicking connect on the database in Data Source Explorer you should be able to see the following view (Figure 7). Note, that our database ‘integrationproject’ includes table ‘users’ which consists of 3 fields: ‘id’, ‘username’, and ‘password’.

database_ecplise

Entity creation

To create entity from database table create JPA project:

File -> New -> JPA -> JPA Project

Enter:
Project name: IntegrationProjectJPA
Target runtime: [Tomcat server configured before]
Configuration: Utility JPA Project with Java 5.0

Following that select:
File -> New -> JPA -> Entities From Tables

Configure custom entities generation as shown in Figure 8.

entity_creation

Copy User.java file which was created to IntegrateProject under the path src/main/java/com/frogdroid/integration/user/entity/ and fix package name. Remove serialVersionUID variable. The content of User.java file is listed below.

package com.frogdroid.integration.user.entity;
 
import java.io.Serializable;
import javax.persistence.*;
 
/**
 * The persistent class for the users database table.
 * 
 */
@Entity
@Table(name = "users")
public class User implements Serializable {
 
    @Id
    private int id;
 
    private String password;
 
    private String username;
 
    public User() {
    }
 
    public int getId() {
        return this.id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getPassword() {
        return this.password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String getUsername() {
        return this.username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
}

XML mapping file creation

We will also need mapping file – it is required by Hibernate factory bean (Hibernate.xml). To create the mapping file select:

File -> New -> Hibernate -> Hibernate XML Mapping File (hbm.xml)

Select: Add Class… and enter: User
Select: User – com.frogdroid.integration.user.entity – IntegrationProject/src/main/java

The file User.hbm.xml will be generated. Copy it to src/main/resources/resources/hibernate/. Change ‘table=”USER”‘ to ‘table=”USERS”‘. If present remove serialVersionUID property. The content of the file is presented below.

<?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>
    <class name="com.frogdroid.integration.user.entity.User" table="USERS">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="assigned" />
        </id>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <property name="username" type="java.lang.String">
            <column name="USERNAME" />
        </property>
    </class>
</hibernate-mapping>

Add mapping file to Hibernate configuration file (src/main/resources/resources/spring/config/Hibernate.xml) as follows:

<property name="mappingResources">
	<list>
		<value>resources/hibernate/User.hbm.xml</value>
	</list>
</property>

Structure of the project after changes is presented in Figure 9.

entity_structure

Test that everything is working OK so far, run from the directory with pom.xml:

mvn clean
mvn compile
mvn war:war

Part 3 of the tutorial can be found at Java Technologies Integration tutorial – part 3.

Updates to the Hibernate configuration of the project can be found in part 5 of the tutorial, which can be found here Java Technologies Integration tutorial – part 5 – Hibernate update.


Introduction

The purpose of this tutorial is to demonstrate the technical solution for integration of 4 leading frameworks:

Such a combination allow the development of you web applications with maximal of flexibility and minimal effort. In addition, the integration with SVN will be also demonstrated to enable the efficient development.

Prerequisites

Before we start you need the following tools:

Setup

Java

Remember to set the JAVA_HOME environment variable to point to the base path of the JDK.

Tomcat

To install Tomcat follow the instructions in installation guide. Remember to set the CATALINA_HOME environment variable to point to the base path of the Tomcat.

Alternative solution is to use Tomcat servers run in Eclipse. To configure it select:

File -> New -> Server -> Server
Select: Apache -> Tomcat 6.0

Choose Tomcat installation directory and click ‘Download and Install’

Tomcat should be downloaded to the directory you chose and server should appear in server list (Servers tab).

Maven

Download Maven from http://maven.apache.org/download.html and unpack it to local directory. Set environment variable M2_HOME to point to directory with Maven.

MySQL and Database

Install and configure MySQL. Create a database named ‘IntegrationProject’ and run the script below to create the “Users” table.

CREATE TABLE `USERS` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(50) NOT NULL,
  `password` VARCHAR(50) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `username` (`username`)
) ENGINE=MyISAM ;

Development

Having all that set up we can finally start the development! First we have to create Maven project.

Maven project

To create the default Maven project we execute:

mvn archetype:generate

Maven downloads number of packages and following that asks about the archetype. Select default one (maven-archetype-quickstart) and define the following values:

Define value for groupId: com.frogdroid.integration
Define value for artifactId: IntegrationProject
Define value for version: 1.0
Define value for package: com.frogdroid.integration

The project should be created!

Eclipse Project

It is possible to tranform Maven project to Eclipse project using command:

mvn eclipse:eclipse

However, for convenience, our approach is to create Dynamic Web Project in Eclipse and integrate Maven project with it. Such approach allows to use Tomcat server integrated with Eclipse. To create Dynamic Web Project we select:

File -> New -> Web -> Dynamic Web Project

Enter:
Project name: IntegrationProject
Target runtime: [Tomcat server configured before] (or leave empty if you decided not to use Tomcat with Eclipse)

Copy the content of the Maven project into you Ecplise project and refresh it. You should see the structure presented in Figure 1.

ecplise_after_maven_copy

Fix the build path as in Figure 2.

ecplise_fix_build_path

There are still some references to external libraries missing but we will deal with that later.

Configure project dependencies and Maven plugins

Maven is framework that deals with dependencies in our project. The convenient way to find the dependencies to be placed in pom.xml file is to use the Maven repository. The dependencies can be copied directly to pom.xml file. We will use following libraries:

  • junit
  • spring
  • hibernate
  • log4j
  • struts2-spring-plugin
  • struts2-dojo-plugin
  • mysql-connector-java
  • persistence-api

If the packages depend on different ones they will be downloaded automatically.
It also uses a number of different plugins to make Java application development more convenient.
In our project we use two plugins:

  • maven-compiler-plugin to configure java version that should be used to compile the sources
  • maven-war-plugin to build war file to be deployed on Tomcat server

pom.xml

The complete pom.xml file is presented below.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
	<modelVersion>4.0.0</modelVersion>
 
	<groupId>com.frogdroid.integration</groupId>
	<artifactId>IntegrationProject</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
 
	<name>IntegrationProject</name>
	<url>http://maven.apache.org</url>
 
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
 
	<dependencies>
 
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.1</version>
		</dependency>
 
 
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring</artifactId>
			<version>2.5.6</version>
		</dependency>
 
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate</artifactId>
			<version>3.2.7.ga</version>
		</dependency>
 
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.16</version>
		</dependency>
 
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-spring-plugin</artifactId>
			<version>2.1.8</version>
		</dependency>
 
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-dojo-plugin</artifactId>
			<version>2.2.1</version>
		</dependency>
 
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.13</version>
		</dependency>
 
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>
 
	</dependencies>
 
	<build>
		<plugins>
 
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
 
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
						</manifest>
					</archive>
				</configuration>
			</plugin>
 
		</plugins>
	</build>
</project>

Test dependencies

To download all the dependencies to local repository and test if project compiles execute:

mvn compile

Missing artifacts

It might happen that some of the artifacts are missing in the Maven repository, .e.g, javax.transaction:jta:jar:1.0.1B. In that case we can install missing artifact in the local repository manually. To do that download the missing artifact (jar file) and follow the instructions on screen. In case of javax.transaction:jta:jar:1.0.1B it can be downloaded from http://www.oracle.com/technetwork/java/javaee/tech/jta-138684.html (change zip extension to jar) and installed using the following command:

mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar -Dfile=jta-1_0_1B.jar

Web application development

Convinient way to develop Web applications with Maven is to use maven-war-plugin. This plugin enforces special project structure. The web sources should be placed in src/main/webapp folder therefore we have to create src/main/webapp folder in our project. Copy whole directory WebContent/WEB-INF to src/main/webapp/. In addition we create src/main/resources folder. The content of this folder is copied directly in WEB-INF/classes after creation of war file. The file structure is presented in Figure 3.

maven_file_structure

War file creation

Having all that done we finally can create war file. To do so, execute the following command:

mvn war:war

The file will be created in target directory. That is also the directory where compiled code is put. Compiled java classes can be found in target/classes. Content of war file can be found in our case in target/IntegrationProject-1.0 and the war file itself in target/IntegrationProject-1.0.war. Configuration of maven-war-plugin indicates that directories that project depends on are included and placed in lib directory, so full path to them is target/IntegrationProject-1.0/WEB-INF/lib.

<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>

The content of target directory after build of war file is presented in Figure 4.

target_folder

Adding dependencies to Ecplise build path

Having all the libraries needed for the development of the project we can finally add them to Eclipse build path (add external jars). Add jar files located in target/IntegrationProject-1.0/WEB-INF/lib to Java build path. Remember to update build path after adding/removing dependencies to/from pom.xml file.

Part 2 of the tutorial can be found at Java Technologies Integration tutorial – part 2


Sometimes Debian and Ubuntu packages have “dfsg” bit in their package name. Out of 40175 packages in Debian unstable, 2015 of them contain string “dfsg”.

The abbreviation stands for The Debian Free Software Guidelines which is a document that defines what kind of software is free (according to Debian Project).

Sometimes it happens that a software packaged is free in general but it contains some non-free elements. An example could be a web application that is shipped with .swf files without their source code. You can see an example of this problem in a package that I maintain – bug #591201. Such files are considered non-free and can not be distributed with Debian. However, the Open Source web application works (mostly) fine without these pesky flash files, so it would be a waste to remove it completely only because of these.

This is when maintainers re-package the application to  remove the non-free elements – and to highlight that fact, they add “dfsg” bit in a package name. The files that don’t comply with DFSG can be put into a separate Debian repository – “contrib” or “non-free” which requires creating one additional package (per repository).

The above is the reason why you sometimes see a single application split into several packages, for example:

abuse (1:0.7.1-1) SDL port of the Abuse action game
abuse-sfx (2.00-9) [non-free] sound effects for Abuse


0. http://cube.dyndns.org/~rsnel/scubed/  (scubed_http)
1. svn checkout http://cube.dyndns.org/svn/scubed/trunk scubed; # get scubed
2. make, su, make install, scubed -V
3. there’s a README file, in the scubed/ directory and on the web-site. basically all is written there  (scubed_readme)
4. it will be a file used, for demonstration purpose. but a real life target is a block device, representing a disk partition. swap this doc’s /dev/loop0 with the name of the real block dev, e.g. /dev/sda9
5. dd if=/dev/urandom of=store bs=1M count=250; # this will create the file “./store” with the size of 250MB
6. losetup /dev/loop0 store;
7. cryptsetup -y create scubed1 /dev/loop0; # this only “creates a mapping with <name> backed by device <device> [man cryptsetup]“. this *does *not encrypt anything, neither resize, it’s no destruction
8. cryptsetup -y create scubed2 /dev/loop0; # the 2nd mapping and the partition (in future) to show how to handle multiple scubed partition
9. scubed /dev/mapper/scubed?; #or: scubed /dev/mapper/scubed1 /dev/mapper/scubed1; #this will show:

root@darkstar:/home/iv# scubed /dev/mapper/scubed1 /dev/mapper/scubed2;
blocksize is 2097664 bytes, overhead is 512 bytes
0000 blocks in /dev/mapper/scubed1 (index 0)
0000 blocks in /dev/mapper/scubed2 (index 1)
0124 blocks unclaimed
0124 blocks total

#notice 0000 blocks, and (index 0)
10. scubed -r 0,25 /dev/mapper/scubed? #this will allocate space, in other words, create the 25MB scubed partition. ABSOLUTELY required to list ALL scubed partitions here (see that ‘?’)

11. scubed /dev/mapper/scubed1 /dev/mapper/scubed2;
root@darkstar:/home/iv# scubed /dev/mapper/scubed1 /dev/mapper/scubed2;
blocksize is 2097664 bytes, overhead is 512 bytes
0025 blocks in /dev/mapper/scubed1 (index 0)
0000 blocks in /dev/mapper/scubed2 (index 1)
0099 blocks unclaimed
0124 blocks total

12. scubed -r 1,25 /dev/mapper/scubed?  #the same for scubed2. 1,25 means “partition with index 1, allocate 25 blocks”
13. scubed /dev/mapper/scubed1 /dev/mapper/scubed2;

root@darkstar:/home/iv# scubed /dev/mapper/scubed1 /dev/mapper/scubed2;
blocksize is 2097664 bytes, overhead is 512 bytes
0025 blocks in /dev/mapper/scubed1 (index 0)
0025 blocks in /dev/mapper/scubed2 (index 1)
0074 blocks unclaimed
0124 blocks total

# there are 0074 blocks free, if it’s a real world, huge waste of disk space
14. scubed -M scubed1.linear /dev/mapper/scubed1  # this “sets up a device mapper table though which the kernel (and filesystems) can access the blocks belonging to /dev/mapper/scubed1 in a normal order” [scubed_readme].
15. cryptsetup -y –cipher serpent-cbc-essiv:sha256 –key-size 256 luksFormat /dev/mapper/scubed1.linear
16. cryptsetup luksOpen /dev/mapper/scubed1.linear scubed1.encrypted
17. mkfs.ext4 /dev/mapper/scubed1.encrypted
18. mount /dev/mapper/scubed1.encrypted ./rmme; cp *.java rmme; umount rmme
19. cryptsetup luksClose /dev/mapper/scubed1.encrypted
20. dmsetup remove scubed1.linear     #scubed itself seems not to have any mechanisms to remove mappings
21. dmsetup remove scubed1; dmsetup remove scubed2;  # scubed2 may be set up similarly to scubed1; steps 13 – 19 with s/scubed1/scubed2/g

22. # done. now the data must be accessed. this time only scubed1 will be created
23. cryptsetup create scubed1 /dev/loop0  #the only way to access previously created scubed partition is to supply the correct password for “cryptsetup create scubed1″. if it’s correct, it will show allocated blocks; if not, “000″:
24. scubed /dev/mapper/scubed?

root@darkstar:/home/iv# scubed /dev/mapper/scubed?
blocksize is 2097664 bytes, overhead is 512 bytes
0025 blocks in /dev/mapper/scubed1 (index 0)
0099 blocks unclaimed
0124 blocks total

25. scubed -M scubed1.linear /dev/mapper/scubed1
26. cryptsetup luksOpen /dev/mapper/scubed1.linear scubed1.encrypted
27. mount /dev/mapper/scubed1.encrypted rmme
28. ls rmme

root@darkstar:/home/iv# ls rmme
Exc.java  MyClass.java  constructors.java  interfce.java  listFiles.java  lost+found  reference.java  sss.java  tryReturn.java

#it’s there.


Sometimes you need to stop a command, if it executes for too long. It’s very simple with a timeout utility from coreutils package. timeout is available in coreutils 8.X – recent enough version is currently in Debian squeeze and sid only. The version in Ubuntu 10.04 is too old (does not provide timeout). Usage is simple:

% timeout <TIME_IN_SECONDS> <COMMAND>

For example:

% timeout 2 sleep 100
% echo $?

The command should stop after 2 seconds and the return code will equal to 124 – this is what timeout returns if a command was timed out.
timeout will send TERM signal to a command which may be intercepted by a command and ignored (process will not stop). You can send KILL signal to make sure that a command will stop:

% timeout -s KILL 2 sleep 100

There is probably no need for me to introduce a great library for processing images: imagemagick. In this mini how-to I will show how I’ve used imagemagick to build an image from few different pieces of media (images and text).

Problem

I wanted to build simple screensaver using public domain images and information. For this, I needed to create a lot of static .gif images with flags of the countries and some basic information about them. For  each image I wanted to use:

  • Country name – I had that as a string somewhere (it’s not relevant for this how-to how was I storing each piece of information – we’ll focus on imagemagick itself)
  • Country flag as .gif file. Each file was slightly different size.
  • Short description of the flag and country.

Solution

Well.. imagemagick and some commandline hackery is the solution of course.
First, I had to create and image from country name. As it turned out, some of the country names can get pretty long and they won’t fit into one line on the image. I have used simple fold utility to wrap longer lines. Imagine that we have name of the country in the variable $name. We process it like this:

echo $name | fold -s -w 30 | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}'

fold -s -w 30 folds our $name without breaking the words (-s) and leaves at most 30 characters per line (-w 30). The scary looking sed command is probably an idea for another whole blog entry – but basically it simply changes newline into two characters: \n. imagemagick will use these to create the newlines when generating an image.
We are ready to generate GIF image that contains the name of the country:

convert -font /usr/share/fonts/truetype/thai/Purisa-BoldOblique.ttf -pointsize 58 -background $BACKGROUND label:"$(echo $name | fold -s -w 30 | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}')" country-name.gif

In a similar fashion I’ve created an image out of a long text:

convert -font /usr/share/fonts/truetype/thai/Purisa-Oblique.ttf -background $BACKGROUND label:"$(fold -w 60 -s texts/long-text.txt | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}')" flag-long-text.gif
  • -fontpoints to a font file I’ve found on my system
  • -pointsize 58 makes for rather big font size
  • -background $BACKGROUND sets the background color to whatever I’ve previously defined in $BACKGROUND, see imagemagick colors
  • label:”….” this is where we are putting our pre-processed text
  • finally, country-name.gif is simply an output filename

Next step: it turned out that the flags I’ve downloaded look much better with the frame around each of them. Also, some of the flags were too wide: I wanted to make them no bigger than 570 pixels. Flags that were smaller than 570 should stay as they are – only bigger ones should be resized. Easy:

convert flag.gif -bordercolor white  -border 6 -bordercolor grey60  -border 1 -resize 570\&gt; flag-with-border.gif
  • options -bordercolor white -border 6 -bordercolor grey60 -border 1 create a 6 pixels wide white border and then 1 pixel wide grey line.
  • -resize 570\> will conditionally resize an image to 570 pixels – if an image is wider than 570 pixels – that is the meaning of the > sign at the end. I had to escape it as \> to prevent bash from interpreting it as redirection
  • like last time, the last argument is the name of the new file: flag-with-border.gif

Now let’s build an empty image. I will overlay other images on top of this one:

convert  -size 1024x768 xc:none -background $BACKGROUND -flatten empty.gif
  • -size 1024x768 is exactly what you think it is
  • xc:none – normally convert takes two arguments: source file and target file. Since we want to create new file, we don’t have any source yet, instead we use this pseudo-image
  • -flatten will remove the transparency

With all the elements ready, all that is left is to put all the images together. composite command will do just that:

#Add country name to empty image
composite -geometry +20+300 country-name.gif empty.gif flag-stage1.gif
#Add long text
composite -geometry +600+300 flag-long-text.gif flag-stage1.gif flag-stage2.gif
#Add flag image
composite -geometry +10+50 flag-with-border.gif flag-stage2.gif flag-full.gif

composite -geometry +X+Y will put an image that is given as a first argument on top of the second image at position (X,Y) and create (third argument) new file. I used it to create final image flag-full.gif step by step.

Here is the final effect:

Saint_Helena_flag

Of course, he next thing you want to do is to wrap those commands in some kind of script – and generate all images automatically.