TechTalks@Tremend with Mircea Marghidanu, lead developer at Unity3D

April 19th, 2016 by pteodorescu in Java, General

Mircea Marghidanu, lead developer at Unity3D was our guest at Tech Talks@Tremend for a presentation on game development, code testing and human perception limits. Not bad for a Monday evening.

Watch the whole session bellow.

Part 1

…and part 2


FRF competition management

January 11th, 2012 by Ioan Cocan in Java, General

As part of an effort to meet UEFA guidelines in footbal competition management, the Romanian FA started an initiative to have a full featured management solution. Initially built in Java (Hibernate/Spring) and Flex we migrated it in 2008 to a Symfony based solution that has been continously updated since then. Although a fine solution at one point, the Flex grew and as it was not modular thought out it became difficult to maintain it.

The solution mantains major leagues (1,2,3), youth and feminin competion data including the official referee delegations. The system allows to generate games based on specific combinations (Bergers). Data is displayed in the official websites: frf.ro and frf-cca.ro (the referees website). Along with several listings and exports the systems provides features such as SMS or email notifications for referees, account info that allows referrees and observers to fill in their personal data, availability, online referee reports and much more.

A FoxPro based solution that was used to mantain player history and memberships was migrated to the solution allowing much more flexible management for player club membership. The database has now over 35.000 registered players since 1960.

The technical solution extensively uses Symfony admin generator, built in caching for information such as competition rankings. Symfony proved to be a very flexible solution with great features for data migration between application versions.

Future plans include registered club access to player information and also an automatic online transfer system. The goal is to have a complete and automated solution that allows all participants in the game to fill in their reports electronically (clubs, referees, observers, FA members).


Tremend 6 years

November 16th, 2011 by Ioan Cocan in Java, General

Tremend teamTremend is now 6 years old, a new year of projects and challenges. So what is new in this past year?

We’ve extended our expertise in technologies such as Drupal and Grails. Published custom modules in Drupal (Drupal Commerce for ePayment), delivered new solutions with Grails (Orange Karaoke). We’ve delivered a highly scalable solution for Orange Romania (Orange My Account), the customer care portal.

We’re up to date with mobile development, released several new apps (iPhone and Android) and mobile sites. A Windows Phone 7 app is on the way, as well.

For the 7th year we plan to deliver more with our expertise and grow into new areas (HTML5, more mobile). And more blog posts.


Spring+JPA with MySQL/Oracle configurations

September 6th, 2010 by Ioan Cocan in Java, General, Spring Framework

Spring Framework

During development for a solution based on Spring+JPA+MySQL/Oracle we came across two settings to watch for.

1. Database isolation level

The default isolation level in MySQL is REPEATABLE READ, different from the default in Oracle (READ_COMMITTED). It seems this is kept for historical reasons related to the replication. Still, the effect is that for example a database query will return the same result, no matter if some other transaction has meanwhile changed the database.

For checking the current MySQL isolation level: SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

For changing the isolation level add: “transaction-isolation = REPEATABLE-READ” to you MySQL configuration.

2. JPA transaction configuration

For those accustomed to Hibernate default configuration, the default JpaTransactionManager comes with a different default for behavior related to transaction configuration. The “globalRollbackOnParticipationFailure” is set to true, that means a failed transaction will trigger a global rollback. If you want to change that and be the decision maker if the global transaction should be rolled back or not, set globalRollbackOnParticipationFailure to false.


Springy: org aspectj weaver reflect ReflectionWorld ReflectionWorldException: warning can’t determine implemented interfaces of missing type

March 30th, 2009 by Marius Hanganu in Java, General, Spring Framework

Here’s a quick one: if you’ve encountered the following error

org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...': Initialization of bean failed; nested exception is org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type ...
 [Xlint:cantFindType]
Caused by: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type ro.tremend.bigg.web.tile.currencyCustomTileRenderer2
 [Xlint:cantFindType]
	at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:163)

And didn’t figure out yet what was the problem, you may want to check your spring version. This error happens in 2.0.2  but it seems it was fixed since 2.0.5.

More here


Dynamically create Spring beans from groovy scripts at runtime

February 24th, 2009 by Marius Hanganu in Java, General

Groovy

In the current project – a java based CMS – we were faced with an interesting problem: how can we dynamically create renderers to power our blocks in the html page (currently all renderers are Java classes and Spring beans also described in the application context files).

Imagine the power of this approach. Especially when Java deployments can be quite a hassle in a multi server environment (deploying sources on the linux machines, wait for a good moment for starting/stopping the servers – which may or may not perform a sensitive operation at that time, synchronize the restart of the web servers, check log files for any errors, etc).

What could be better than having your Spring beans dinamically created from the administration panel? No server restarts, no deployments. Just keep your Groovy scripts in the database and make any modification realtime.

Achieving the programatic creation of Spring beans from groovy scripts can be done in four steps:

1. load the groovy script and parse it into a java Class
2. create a bean definition using the previously loaded class
3. inject any other beans into your bean definition
4. register the bean definition and get a handle on the bean created

Of course, you cannot declare variables as instances of the Java class defined in the groovy script. Or you may do it programatically through reflection. But it is much simpler (if the project suits these needs) to have a base interface for all your dynamic beans and after those 4 steps, simply cast the bean created to the Java interface. So you might add two more steps to the previous four:

0. declare a base interface for your all your classes declared in groovy scripts
5. cast the created bean to the base interface so that you can use it in your code

The code is actually pretty simple. But you can hardly find any article/post on the subject. Most of them discuss an older version of Spring (1.x), while my code had to work with Spring 2.0.x – which is completely different in terms of the API calls needed to create a bean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class GroovyTemplateEngineImpl extends DefaultListableBeanFactory implements ApplicationContextAware {
    public BaseInterface createOrUpdateBean(String rendererName, String code) throws Exception, ClassNotFoundException {
 
        // 1. load the groovy script and parse it into a class
        GroovyClassLoader gcl = new GroovyClassLoader(getClassLoader());
        Class clazz = gcl.parseClass(groovyScriptAsAString);
 
        // 2. create the bean definition
        AbstractBeanDefinition beanDef = BeanDefinitionReaderUtils.createBeanDefinition( "parentBean", packageName + "." + className, gcl);
 
        // 3. inject here any attributes that would normally be passed using spring XML configuration files
        beanDef.setAttribute("attr1", bean1);
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory) appCtx.getAutowireCapableBeanFactory();
 
        // 4. Create the bean - I'm using the class name as the bean name
        factory.registerBeanDefinition(className, beanDef);
        Object bean = factory.createBean(clazz, AUTOWIRE_BY_NAME, false);
 
        // 5. further on you can cast it to any interface
        return (BaseInterface) bean;
    }
}

You will also need to add to the previous class a setter for application context to be injected (the class needs to implement ApplicationContextAware).

Please note that this code only works from spring version 2.0.3 and up. If you’re using a lower version, you’ll likely encounter this exception:

1
2
3
Caused by: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: 
warning can't determine implemented interfaces of missing type .... 
[Xlint:cantFindType]

Good luck groovying!


How to order by a custom SQL formula/expression when using hibernate Criteria API

June 10th, 2008 by spostelnicu in Java, General

In our current project we are using Spring + Hibernate Annotations.
Today I needed to use something like:

1
2
3
SELECT DISTINCT t.id FROM MyClass t
 WHERE .....
 ORDER BY (a + b) DESC

where a and b are properties of MyClass (columns in the “my_class” table).

The “where …” expression must be generated dynamically based on the user input, so we are using Criteria API to generate the query as such:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Criteria criteria = getSession().createCriteria(MyClass.class);
criteria.setProjection(Projections.distinct(Projections.id()));
 
// Some custom dynamic conditions
criteria.add(Restrictions.gt("createdDate", afterDate));
criteria.add(Restrictions.in("state", approvedStates));
criteria.add(Restrictions.isNull("deletedDate"));
if (includedCategories != null || excludedCategories != null) {
    Criteria categoryCriteria = criteria.createCriteria("category");
    if (includedCategories != null) {
        for (String categoryPrefix : includedCategories) {
            categoryCriteria.add(Restrictions.like("path", categoryPrefix + "%"));
        }
    }
    if (excludedCategories != null) {
        for (String categoryPrefix : excludedCategories) {
            categoryCriteria.add(Restrictions.not(Restrictions.like("path", categoryPrefix + "%")));
        }
    }
}
 
criteria.add(Restrictions.sqlRestriction("(a + b) > 1"));
 
// Custom ordering by some SQL formula/expression
criteria.addOrder(Order.desc("a + b"));
 
return criteria.list();

Now, the problem is that the class Order does not support custom SQL formula/expression…

So my solution was to derive my own class as such:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package ro.tremend.util.hibernate;
 
import org.hibernate.criterion.Order;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
 
/**
 * Extends {@link org.hibernate.criterion.Order} to allow ordering by an SQL formula passed by the user.
 * Is simply appends the <code>sqlFormula</code> passed by the user to the resulting SQL query, without any verification.
 * @author Sorin Postelnicu
 * @since Jun 10, 2008
 */
public class OrderBySqlFormula extends Order {
    private String sqlFormula;
 
    /**
     * Constructor for Order.
     * @param sqlFormula an SQL formula that will be appended to the resulting SQL query
     */
    protected OrderBySqlFormula(String sqlFormula) {
        super(sqlFormula, true);
        this.sqlFormula = sqlFormula;
    }
 
    public String toString() {
        return sqlFormula;
    }
 
    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        return sqlFormula;
    }
 
    /**
     * Custom order
     *
     * @param sqlFormula an SQL formula that will be appended to the resulting SQL query
     * @return Order
     */
    public static Order sqlFormula(String sqlFormula) {
        return new OrderBySqlFormula(sqlFormula);
    }
}

Now, to use the custom ordering, I included the following line:

1
        criteria.addOrder(OrderBySqlFormula.sqlFormula("(a + b) desc"));

How to use the request Referer as the targetUrl when using Acegi Security for Spring

September 7th, 2007 by spostelnicu in Java, General

Suppose that my login form is integrated in another page and I want to return to that page that integrated my login page (so the original page).
How do you do that in ACEGI ?

My solution was to extend the AuthenticationProcessingFilter and add a property named useRefererAsTargetUrl.
If this property is set to true, then the AuthenticationProcessingFilter will redirect to the value of the request Referer header upon successful authentication, unless the targetUrl can be taken from a SavedRequest, (which usually means that the authentication request was caused by an AccessDeniedException or AuthenticationException thrown within the filter chain). If alwaysUseDefaultTargetUrl is also set to true, then the defaultTargetUrl will be used, and this flag will be ignored.
This flag defaults to false, which is the default behaviour of AuthenticationProcessingFilter.

To set it to true, simply use the following Spring configuration:

1
2
3
4
5
6
7
8
<bean id="authenticationProcessingFilter" class="ro.tremend.web.filters.ExtendedAuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationFailureUrl" value="/#invalid_login"/>
    <property name="defaultTargetUrl" value="/"/>
    <property name="useRefererAsTargetUrl" value="true"/>
    <property name="filterProcessesUrl" value="/web_login_check"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

The source code for the class is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class ExtendedAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
 
    /**
     * If <code>true</code>, will redirect to the value of the request Referer header upon successful authentication,
     * unless the targetUrl can be taken from a {@link org.acegisecurity.ui.savedrequest.SavedRequest}
     * (which usually means that the authentication request was caused by an
     * <code>AccessDeniedException</code> or <code>AuthenticationException</code> thrown within the filter chain).
     * If alwaysUseDefaultTargetUrl is also set to true, then the defaultTargetUrl will be used,
     * and this flag will be ignored.
     * This flag defaults to <code>false</code>, which is the default behaviour of AuthenticationProcessingFilter.
     */
    private boolean useRefererAsTargetUrl = false;
 
    protected String determineTargetUrl(HttpServletRequest request) {
        // Don't attempt to obtain the url from the saved request if
        // alwaysUsedefaultTargetUrl is set
        if (isAlwaysUseDefaultTargetUrl()) {
            return getDefaultTargetUrl();
        }
 
        String targetUrl = obtainFullRequestUrl(request);
 
        if (targetUrl == null && useRefererAsTargetUrl) {
            targetUrl = obtainRequestRefererUrl(request);
        }
 
        if (targetUrl == null) {
            targetUrl = getDefaultTargetUrl();
        }
 
        return targetUrl;
    }
 
    public static String obtainRequestRefererUrl(HttpServletRequest request) {
        return request.getHeader(HttpUtils.HTTP_HEADER_REFERER);
    }
 
    public boolean isUseRefererAsTargetUrl() {
        return useRefererAsTargetUrl;
    }
 
    public void setUseRefererAsTargetUrl(boolean useRefererAsTargetUrl) {
        this.useRefererAsTargetUrl = useRefererAsTargetUrl;
    }
}

Maybe (in a future release of Acegi Security) this feature will simply be integrated in AbstractProcessingFilter, where it belongs…


Create a Solr filter that replaces diacritics

August 28th, 2007 by Sebastian Mitroi in Java, General

Some languages (like Romanian) have special characters (diacritics, often called accent marks). It’s generally useful to remove diacritic marks from characters, for example when you create an index with Solr. You don’t want to index text with these characters because you want to find for example both words “propriet??i” and “proprietati”. If you are using Solr to index your text you have to create a Solr filter.
First of all you have to put the filter in the schema.xml configuration file :


<fieldtype name="text_st" class="solr.TextField" positionIncrementGap="100">
            <analyzer>
                <tokenizer class="solr.StandardTokenizerFactory"/>
                // ... some other filters for example lower case filter
                <filter class="solr.LowerCaseFilterFactory"/>                
                <filter class="ro.tremend.solr.diacritics.DiacriticsFilterFactory"/>                

            </analyzer>
</fieldtype>

Then create 3 small classes and a properties file. The filter factory for Solr DiacriticsFilterFactory :

package ro.tremend.solr.diacritics;

import org.apache.lucene.analysis.TokenStream;
import org.apache.solr.analysis.BaseTokenFilterFactory;

/**
 * Create a Solr Filter Factory for diacritics
 * 
 * @author Sebastian
 * 
 */
public class DiacriticsFilterFactory extends BaseTokenFilterFactory {
	public TokenStream create(TokenStream input) {
		return new DiacriticsFilter(input);
	}
}

Now you have to create the filter class DiacriticsFilter :

package ro.tremend.solr.diacritics;

import org.apache.lucene.analysis.*;
import java.io.IOException;

/**
 * Create the diacritics filter
 * 
 * @author Sebastian
 * 
 */
public final class DiacriticsFilter extends TokenFilter {
	public DiacriticsFilter(TokenStream in) {
		super(in);
	}

	public final Token next() throws IOException {
		Token t = input.next();

		if (t == null)
			return null;

		t.setTermText(DiacriticsUtils.replaceDiacritics(t.termText()));
		return t;
	}
}

and finally the class that does the work DiacriticsUtils :

package ro.tremend.solr.diacritics;

import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * Replace romanian characters
 * 
 * @author Sebastian
 * 
 */
public class DiacriticsUtils {
	private static Map<String, String> diacritics = new HashMap<String, String>();

	static {
		// Get diacritics from diacritics.properties
		try {
			ResourceBundle resource = ResourceBundle.getBundle("diacritics");
			Set keySet = resource.keySet();
			for (String key : keySet) {
				diacritics.put(key, resource.getString(key));
			}
		} catch (MissingResourceException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Replace all diacritics in a string
	 * 
	 * @param s the string
	 * @return the string without diacritics
	 */
	public static String replaceDiacritics(String s) {
		for (String key : diacritics.keySet()) {
			s = s.replaceAll(key, diacritics.get(key));
		}
		return s;
	}

	public static Map<String, String> getDiacritics() {
		return diacritics;
	}
}

This class needs a properties file with the diacritics you want to replace:
diacritics.properties

\\u0102=A
\\u0103=a
... define all your language specific characters

 


Now the index will not contain diacritics, but you have to remove the diacritics from the query too. To do that just write this:

textToFind = DiacriticsUtils.replaceDiacritics(textToFind);

 


I hope this will help.


Avoiding SQL joins with java enums

August 28th, 2007 by Sebastian Mitroi in Java, General

Lets say you have a Coffee object and 3 sizes for coffee (small, medium and large).You can create a Coffee class like this

public class Coffee {
	private Long id;
	// add other propeties
	private CoffeeSize coffeeSize;


	// ... setters and getters
}	

and the CoffeeSize class:

public class CoffeeSize {		
	private int id;
	private String name;
	private String i18nKey;
	
	// ... setters and getters
}

But every time you load a Coffee object you execute a sql join to load the CoffeeSize.

Of course you can create a CoffeeSize object and define some public static final CoffeeSize objects, but with java 1.5 you can do something like this :
create a java enum named CoffeeSize and persists just the CoffeeSize id.

package coffee;

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

public enum CoffeeSize {
	SMALL(1, "Small", "coffeeSize.small"),
	MEDIUM(1, "Medium", "coffeeSize.medium"),
	LARGE(1, "Large", "coffeeSize.large");
		
	private int id;
	private String name;
	private String i18nKey;
	
	private static Map coffeeSizes = new HashMap();
	
	static{
		CoffeeSize[] coffeeSizesArray = CoffeeSize.values();
		for (CoffeeSize coffeeSize : coffeeSizesArray) {
			coffeeSizes.put(coffeeSize.getId(), coffeeSize);
		}		
	}
	
	private CoffeeSize(int id, String name, String key) {
		this.id = id;
		this.name = name;
		i18nKey = key;
	}

	public int getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	/**
	 * This is an i18n key defined in message.properties
	 * @return the i18n key
	 */
	public String getI18nKey() {
		return i18nKey;
	}
	
	/**
	 * For the id stored in database get the CoffeeSize object
	 * @param id the id stored in database
	 * @return the {@link CoffeeSize} object
	 */
	public static CoffeeSize getCoffeeSizeById(Integer id) {
		return CoffeeSize.coffeeSizes.get(id);
	}	
}

The Coffee object will look something like this (I used hibernate and ejb3 annotations):

package coffee;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "coffee")
public class Coffee {
	private Long id;
	// add other propeties
	private Integer coffeeSizeId;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Long getId() {
		return id;
	}

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

	public Integer getCoffeeSizeId() {
		return coffeeSizeId;
	}

	public void setCoffeeSizeId(Integer coffeeSizeId) {
		this.coffeeSizeId = coffeeSizeId;
	}

	@Transient
	public CoffeeSize getCoffeeSize(){
		return CoffeeSize.getCoffeeSizeById(coffeeSizeId);
	}
}


Look at the getCoffeeSize method: it is transient(is not persisted). The persisted fields are id and coffeeSizeId. You avoid a sql join putting private Integer coffeeSizeId instead private CoffeeSize coffeeSize and create a getCoffeeSize method that returns a CoffeeSize object. All the CoffeeSize objects are loaded in memory in the static map coffeeSizes.

But remember, this will work only if you don’t want to add a new size for coffee without recompiling and deploying your application.


Hibernate annotations – default value

August 27th, 2007 by Marius Hanganu in Java, General

If you wanted to set the default value using hibernate annotations, you’ve probably had some difficulties, as it was the case for me. Some posts on the web talk about default values to the members of the Java class. That is, if you declare

class Test {

    private Integer count = 3;

    @Column(name = “count”, nullable = false)
public Long getCount() {
return Count;
}

}

you should have the default value set in the database.

Well, this does not seem to work (at least not for me). So the first solution I found involves the usage of “columndefinition”. Hence, it is database dependent, since Hibernate specifies the usage of “columndefinition” attribute for database specific declarations. The following will work well with MySQL – the database of choice for my current project:

class Test {    private Integer count = 3;

    @Column(name = “count”, nullable = false, columnDefinition = “bigint(20) default 0”)
public Long getCount() {
return Count;
}

}

Again – this is database dependent, so use it if your project is db dependent.


How to set the default charset to utf-8 for create table when using hibernate with java persistence annotations

August 14th, 2007 by spostelnicu in Java, General

Yesterday I encountered a problem when trying to persist a String value into a MySQL column of type ‘text‘ (the problem also occurs for column types ‘tinytext‘, ‘mediumtext‘ etc.)

The first confusing thing was that the error message returned by mysql was
java.sql.BatchUpdateException: Data truncation: Data too long for column 'my_column'

The confusing thing was that the column was of type ‘text‘ (length=65536), and I then changed it to type ‘mediumtext‘ (length=16777215), but the value that I was trying to persist had only around 6000 characters, so it was not a problem with the data length.
Instead the one thing that was noticeable about my String value was that it contained non-ASCII characters (particularly Romanian characters with diacritics).

After a little search on the web, I found the following mysql bug description http://bugs.mysql.com/bug.php?id=17872
A comment on that page ([8 Mar 2006 9:53] [ name withheld ]) also contains some more links to similar bug descriptions.

Now it was a little clearer that the problem was caused by the Romanian characters (and the error message was just stupid), so the next thing to do was to figure out why the database table didn’t store UTF-8 characters.

Although I created the database with
create database mydb character set utf8 collate utf8_general_ci;
still the tables created inside it had the collation latin1_swedish_ci.

My application uses Hibernate for persistence and uses java persistence annotations to specify the hibernate mappings.

In my case the code is something like:


import javax.persistence.*;

@Entity
@Table(name = "my_table")
public class MyClass implements Serializable {
    private String myValue;

    @Column(name = "my_column", columnDefinition = "mediumtext", length = 16777215)
    public String getMyValue() {
        return this.myValue;
    }

    public void setMyValue(String value) {
        this.myValue = value;
    }
}

The database schema is automatically generated based on the classes and hibernate mappings, by using the following ant target:


    <taskdef name="hibernatetool"
             classname="org.hibernate.tool.ant.HibernateToolTask"
             classpathref="project.classpath"/>

    <target name="hbm2ddl-schema"
            description="Generates the database schema from hibernate mappings">
        <hibernatetool destdir="">
            <classpath refid="project.classpath"/>
            <annotationconfiguration configurationfile="${classes.dir}/hibernate.cfg.xml"/>
            <hbm2ddl export="true" drop="false" create="true" haltonerror="true"/>
        </hibernatetool>
    </target>

If I had created the database tables by writing the SQL DDL by hand, I would have used the following script:


  create table `my_table` (
      `Id` int(11) NOT NULL auto_increment,
      `my_column` mediumtext NOT NULL default ”,
      ......
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

But in my case the database schema is automatically generated by HibernateTools, so I have to specify the default charset for the table somewhere in the @Table annotation, or hibernate configuration, or hibernatetool parameters.

After trying a few options (and I must admit I did not search thoroughly, so if you know of some better way to specify the default charset, please leave a comment), I chose the following solution:
I implemented my own custom org.hibernate.dialect.Dialect, by subclassing org.hibernate.dialect.MySQL5InnoDBDialect:


import org.hibernate.dialect.MySQL5InnoDBDialect;

/**
 * Extends MySQL5InnoDBDialect and sets the default charset to be UTF-8
 * @author Sorin Postelnicu
 * @since Aug 13, 2007
 */
public class CustomMysqlDialect extends MySQL5InnoDBDialect {

    public String getTableTypeString() {
        return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
}

and used it in my hibernate.cfg.xml:


<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">my.package.CustomMysqlDialect</property>
        .....
    </session-factory>
</hibernate-configuration>

Hibernate schema maintenance

July 31st, 2007 by Ioan Cocan in Java, General

Hibernate provides a nice way to keep your DB schema in sync with the model. At least 2 choices are available:

– have the hibernate.hbm2ddl.auto set to auto during development

– use various utilities: SchemaExportTask or HibernateToolTask(newer) to generate the full DB schema

For development, first choice worked except for one thing: index creation. All columns were properly created but no index defined. As I found no workaround to that, the only solution was to generate the whole schema.

What if the Hibernate model mixed hbm.xml files with annotations (reused components, mostly)? The SchemaExportTask or HibernateToolTask do not handle the mixed model not to mention the integration with Spring and the missing hibernate.cfg.xml file required by HibernateToolTask.

Only one solution: go to the code and generate the schema by calling the code directly. Easy task actually, I’ve placed the code in a quick Junit test with Spring auto-injection:

/**
 * Maintains DB schema
 *
 * @author icocan
 */
public class SchemaMaintenanceTest extends BaseCommitTestCase {

    private LocalSessionFactoryBean localSessionFactoryBean;

    public void testExportDDL() {
        Configuration configuration = localSessionFactoryBean.getConfiguration();
        SchemaExport export = new SchemaExport(configuration);
        export.setOutputFile("sql.ddl");
        export.setDelimiter(";");
        export.execute(false, false, false, false);
    }

    public void setLocalSessionFactoryBean(LocalSessionFactoryBean localSessionFactoryBean) {
        this.localSessionFactoryBean = localSessionFactoryBean;
    }
}

DWR, JSON and IE6: beware keywords

July 20th, 2007 by Ioan Cocan in Java, General

Spent quite a bit of time investigating an “IE bug”. What happened: a particular AJAX request would work fine in Firefox but nothing would happen in IE6. Obvious steps were to monitor request and response (all fine), JS imports in files (all fine).

The final explanation was quite simple: that particular object (Customer), contained a field called “function”. The JSON string returned by DWR was correctly interpreted by FF but would make IE6 hang. The simple solution: rename the field and beware any other JS keywords.


Hibernate, UTF-8 and SQL Server 2005

May 23rd, 2007 by Ioan Cocan in Java, General

I found out today that MS Sql server seems to handle Unicode in a very special way. Instead of having some support a database or table level, each Unicode column have to be created as “national”. That is be either nchar, nvarchar or ntext.

Ms SQL Server 2005 seems to go one step further by announcing future deprecation for ntext, text and image types.

From Sql Server 2005 notes:

ntext, text, and image data types will be removed in a future version of Microsoft SQL Server. Avoid using these data types in new development work, and plan to modify applications that currently use them. Use nvarchar(max), varchar(max), and varbinary(max) instead.”

When working with Hibernate it seems there is no dialect to handle Unicode integration properly. You have to get down and write a custom dialect that maps to the new data types.

/**
 * Unicode support in SQL Server
 *
 * @author icocan
 */
public class UnicodeSQLServerDialect extends SQLServerDialect {

    public UnicodeSQLServerDialect() {
        super();

        // Use Unicode Characters
        registerColumnType(Types.VARCHAR, 255, "nvarchar($l)");
        registerColumnType(Types.CHAR, "nchar(1)");
        registerColumnType(Types.CLOB, "nvarchar(max)");

        // Microsoft SQL Server 2000 supports bigint and bit
        registerColumnType(Types.BIGINT, "bigint");
        registerColumnType(Types.BIT, "bit");
    }
}

« Previous Entries