domenica, dicembre 28, 2008

BLOB type in MySQL

I had this exception when I was trying to insert a big image in a BLOB column using MySQL.

java.sql.BatchUpdateException: Data truncation: Data too long for column 'picture' at row 1


The problem didn't happen with small images, i.e. with the size of 2,3Kb. After spent some time to investigate about the problem, I understood that the reason is due to the BLOB type in MySQL whose maximum size is 64k. Therefore if you want to store big binary data in a MySQL database you need to use another blob type as MEDIUMBLOB or LONGBLOB.
If you are using JPA annotations to define your tables you need to specify the length of your BLOB attribute using the @Column annotation.
Here is what I have defined for the picture attribute used in jugevents application.

@Lob
@Basic(fetch = FetchType.LAZY)
@Column(length=1048576)
public byte[] getPicture() {
return picture;
}

In this way the type of the column corresponding to the picture attribute will be MEDIUMBLOB instead of BLOB and you won't get that exception

venerdì, dicembre 05, 2008

Auto injected spring beans

A colleague of mine asked me to solve a problem about using beans, configured using the spring container, in legacy code.
Basically he couldn't change the way those beans are created but he wanted to be able to inject their properties using a spring configuration file.
This is the way he wants to create an instance of the class BeanAutoInjecting.

BeanAutoInjecting bai = new BeanAutoInjecting();

The class BeanAutoInjecting has its attributes injected by spring container but we don't want to have any trace of Spring in the code that use this class.
A friend of mine, Lucio, proposed me to use the class AutowiredAnnotationBeanPostProcessor to sort out this problem.
Therefore we have to modify the constructor of the class BeanAutoInjecting in this way:

public BeanAutoInjecting()
{
ApplicationContext ctx = SpringLoader.getApplicationContext();
AutowiredAnnotationBeanPostProcessor aabpp = (AutowiredAnnotationBeanPostProcessor)ctx.getBean(
"org.springframework.context.annotation.
internalAutowiredAnnotationProcessor");
aabpp.processInjection(this);
}

The trick is to define a dummy constructor and to instruct the spring container to use it. Here the dummy constructor

public BeanAutoInjecting(int a)
{
System.out.println("I am the dummy constructor!");
}

Here the definition of the bean and the auto-wiring directive in the spring configuration file.

<!-- auto wiring directive -->
<context:component-scan base-package="spikes.springexamples"/>
---------------------------
<!-- bean definition with dummy constructor ->
<bean name="beanAutoInjecting" class="spikes.springexamples.BeanAutoInjecting">
<constructor-arg>15</constructor-arg>
</bean>

That's cool I would say, I am able to use a spring managed bean in my legacy code creating it out of the spring container!!!