Showing posts with label annotation. Show all posts
Showing posts with label annotation. Show all posts

Tuesday, April 21, 2015

spring annotations i never had the chance to use part 1: @primary

Today I remembered an old friend of mine (@primary) with whom we met from tutorials to tutorials. You know that in Spring @Autowired annotation works by type, that is if Spring finds an eligible bean that matches in terms of type it will inject it in. Let's see it on an example.

Assume I have two Singer classes; OperaSinger and MetalSinger.


@Component
public class MetalSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
They both implement the Singer interface.
public interface Singer {
    String sing(String lyrics);
}
And lets define a SingerService and inject the Singer bean inside.
@Component
public class SingerService {
    private static final Logger logger = LoggerFactory.getLogger(SingerService.class);

    @Autowired
    private Singer singer;

    public String sing(){
        return singer.sing("song lyrics");
    }
}
What do you think; which Singer will be injected inside? Here's the result:
 I am singing with DIO voice: song lyrics.

This is because OperaSinger is not defined as Component or Service so Spring does not have a clue about it. If we add @Component annotion to it:


@Component
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
Than I'll get this exception:

 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

The reason is quite plain to see. If I have more than one bean with same type, and if I use @Autowired annotion which binds type I'll have this exception. Spring does not have a clue which Singer it should use.

Let's favor a music genre and tell Spring to use OperaSinger as Primary.


@Primary
@Component
public class OperaSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
If we do the SingerService call we will get:
"I am singing in Bocelli voice: song lyrics"
That is because we choose OperaSinger as Primary which means "if you get confused with types you better use this one". Another approach would be the use of qualifier names which directly maps names to beans.

Wednesday, December 10, 2014

unknown column 'date' in 'field list'

When working on a project in which we use hibernate, I get
Unknown column 'date' in 'field list'
as exception. The spring exception was:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.ID as ID3010_0_, this_.date as date3010_0_,
The only field I have in my entity named 'date' is not marked with column annotation. So it should not be mapped to database table and thus should not be used in the query right? No, think again. Every field in the entity class is mapped and column annotation is optional. So if you ever want hibernate to ignore a field in your entity (because either this field is not present in the table or you don't want to use it somehow), use transient annotation. So,
@Entity
public class MyEntity implements Serializable
{
    private String date;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;
must become this
@Entity
public class MyEntity implements Serializable
{
    @Transient
    private String date;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;