jligeza
jligeza

Reputation: 4703

mongodb DAO sets all attributes to null before save()

I try to receive bean of a class from context, and then save it in a mongodb collection. The problem is, all of its attributes are, for unknown reasons, set to null right before saving. It works perfectly well when I try to save objects in database created by new operator, but not with beans:

public static void main(String[] args) {
    ApplicationContext ctx;
    ctx = new ClassPathXmlApplicationContext("context.xml");
    Komputer komputer = (Komputer)ctx.getBean("komputer");

    Dao dao = (Dao)ctx.getBean(Dao.class);
    dao.deleteAll();

    System.out.println("inserting: " + komputer.getTyp());
    dao.save(komputer); // sets everything to null and puts in db

    Komputer new_komputer = new Komputer();
    new_komputer.setTyp("test");

    System.out.println("inserting: " + komputer.getTyp());
    dao.save(new_komputer); // correctly puts in db

    Iterable <Komputer> komputer_iterable = dao.findAll();
    System.out.println("List: ");
    for (Komputer komputer : komputer_iterable) {
        System.out.println("id:" + komputer.getId() + ", typ: " + komputer.getTyp());
    }
}

Result printed in console:

inserting: Intel Pentium B970
13:33:38.719 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Inserting DBObject containing fields: [_class, _id, obwodKola, liczbaLosowa] in collection: komputer
13:33:38.720 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[lab_test]
inserting: test
13:33:38.726 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Inserting DBObject containing fields: [_class, _id, typ, obwodKola, liczbaLosowa] in collection: komputer
13:33:38.726 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[lab_test]
13:33:38.730 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - find using query: { } fields: null for class: class org.zut.lab1.Komputer in collection: komputer
13:33:38.731 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[lab_test]
List: 
id:56657ca244ae837d313d8b29, typ: null
id:56657ca244ae837d313d8b2a, typ: test

Of course, all of the first objects attributes were set correctly.

This is how dao class looks like:

import org.springframework.data.repository.CrudRepository;

public interface Dao extends CrudRepository<Komputer, String> {

}

And also Komputer class:

import org.springframework.data.annotation.Id;

public class Komputer {
    @Id
    private String id;
    private Procesor procesor;
    private String typ;
    private float obwodKola; // 2 * pi * r
    private float liczbaLosowa;

    public void setProcesor(Procesor procesor) {
        this.procesor = procesor;
    }

    public Procesor getProcesor() {
        return this.procesor;
    }

    public void setTyp(String typ) {
        this.typ = typ;
    }

    public String getTyp() {
        return this.typ;
    }   

    public float getObwodKola() {
        return obwodKola;
    }

    public void setObwodKola(float obwodKola) {
        this.obwodKola = obwodKola;
    }

    public float getLiczbaLosowa() {
        return liczbaLosowa;
    }

    public void setLiczbaLosowa(float liczbaLosowa) {
        this.liczbaLosowa = liczbaLosowa;
    }

    public String getId() {
        return id;
    }

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

Beans in context.xml file:

<mongo:mongo id="mongo" host="localhost" port="27017" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg ref="mongo" />
    <constructor-arg name="databaseName" value="lab_test" />
</bean>

<mongo:repositories base-package="org.zut.lab1"></mongo:repositories> 

<bean id="procesor" class="org.zut.lab1.Procesor">
    <property name="iloscRdzeni" value="4"/>
    <property name="czestotliwosc" value="300000"/>
</bean>

<bean id="komputer" class="org.zut.lab1.Komputer">
    <property name="liczbaLosowa" value="#{T(java.lang.Math).random() * procesor.czestotliwosc}"/>
    <property name="procesor" ref="procesor"/>
    <property name="obwodKola" value="#{T(java.lang.Math).PI * 2 * procesor.getIloscRdzeni()}"/>
    <property name="typ" value="Intel Pentium B970"/>
</bean>

This makes me totally disoriented. What am I doing wrong?

Upvotes: 0

Views: 802

Answers (1)

Valijon
Valijon

Reputation: 13113

Basically, Spring AOP creates a Proxy for bean instance with id komputer.

As it proxy, it calls proxied methods (like when you mock with Mockito), but original attributes are null. If you debug your code with some IDE (Eclipse, for example), you can see what's happening.

So, when you save proxied instance, it takes attribute's value, not getters.

If you remove aop proxy from context, komputer bean will be saved correctly.

<aop:aspectj-autoproxy/>
....
<aop:config>
    <aop:aspect ref="profiler">
        <aop:pointcut expression="execution(* org.zut.lab1.Komputer.oblicz(..)) and args(czas)"
         id="test"/>
        <aop:around method="profile" pointcut-ref="test"/>
    </aop:aspect>
</aop:config>

Proxy for Komputer instance

Upvotes: 1

Related Questions