IoC in Morphia BasicDao

1,161 views
Skip to first unread message

Sonar

unread,
Jan 3, 2011, 12:55:35 PM1/3/11
to Morphia
Greetings,

I should definitely bring this to a broader circle. In my opinion, the
lack of default constructor in BasicDao is a bad thing. Using this
class in Spring application becomes a little problematic.

My arguments are:

1) Inability to postpone initialization of Dao internals up until the
moment of Srping context is initialized
2) More code. I have a dozen of BasicDao subclasses. All of them must
have 4 parameter constructor (entity name, mongo, morphia, db name)
3) Inability to use @Repository annotation which allows me to reduce
amount of xml configuration

Any thoughts on this subject are appreciated.

Scott Hernandez

unread,
Jan 3, 2011, 1:10:50 PM1/3/11
to mor...@googlegroups.com
I use guice and it supports this without xml; I'm sure spring does
too... but I can't help you there.

If a class has hard dependencies, in which the object is not valid
without them, then the constructor is the place for them. BasicDAO is
not valid with those fields. It is very clear from the constructors
which options are required, and in what combination. If there was a
no-args constructor it would be less-clear what is fields are required
and would result in an initial invalid and broken state.

My feeling is that if you want that, then you can copy the code for
yourself. It is not much code.

Sonar

unread,
Jan 3, 2011, 1:33:52 PM1/3/11
to Morphia
Copying code of actively developing project is even worse. I'd rather
modified the Morphia code. This way you will bring much more comfort
to Spring users.


On Jan 3, 1:10 pm, Scott Hernandez <scotthernan...@gmail.com> wrote:
> I use guice and it supports this without xml; I'm sure spring does
> too... but I can't help you there.
>
> If a class has hard dependencies, in which the object is not valid
> without them, then the constructor is the place for them. BasicDAO is
> not valid with those fields. It is very clear from the constructors
> which options are required, and in what combination. If there was a
> no-args constructor it would be less-clear what is fields are required
> and would result in an initial invalid and broken state.
>
> My feeling is that if you want that, then you can copy the code for
> yourself. It is not much code.
>

Andre

unread,
Jan 3, 2011, 1:47:52 PM1/3/11
to mor...@googlegroups.com, Morphia
What about an extension for spring users?

Sonar

unread,
Jan 3, 2011, 2:03:39 PM1/3/11
to Morphia
What do you mean?

On Jan 3, 1:47 pm, Andre <mavec...@gmail.com> wrote:
> What about an extension for spring users?
>

Andre

unread,
Jan 3, 2011, 3:12:57 PM1/3/11
to mor...@googlegroups.com, Morphia
Anything like SpringBasicDao...

Sonar

unread,
Jan 3, 2011, 3:16:45 PM1/3/11
to Morphia
I don't mind this at all. Whatever is easier for Scott...

On Jan 3, 3:12 pm, Andre <mavec...@gmail.com> wrote:
> Anything like SpringBasicDao...
>

Scott Hernandez

unread,
Jan 3, 2011, 3:39:08 PM1/3/11
to mor...@googlegroups.com
From what I understand you can simply use @Autowire on each of your
inherited classes. As long as you have each of the constructor
parameters wired, and available for injection, then it should just
work, no?
http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation

This seems like a spring issue, and not something that should be
changed, as I mentioned. The constructors are correct and appropriate.

If you want to build some sort of extension for spring to simply
configuration I'm all ears, but since I don't use spring I can't very
easily contribute. I'm happy to look at an extension project for
inclusion if someone comes up with one.

Sonar

unread,
Jan 3, 2011, 4:13:58 PM1/3/11
to Morphia
This is not a spring issue, for sure. What I do not want to do is to
manually wire constructor parameters in Spring config and have long
constructor in all BasicDao subclasses. This can be achieved with the
default constructor, which allows creation of "empty" dao object and
only after that injecting of all necessary dependencies into it
(Spring does it for me)

Thanks

On Jan 3, 3:39 pm, Scott Hernandez <scotthernan...@gmail.com> wrote:
> From what I understand you can simply use @Autowire on each of your
> inherited classes. As long as you have each of the constructor
> parameters wired, and available for injection, then it should just
> work, no?http://static.springsource.org/spring/docs/2.5.x/reference/beans.html...
>
> This seems like a spring issue, and not something that should be
> changed, as I mentioned. The constructors are correct and appropriate.
>
> If you want to build some sort of extension for spring to simply
> configuration I'm all ears, but since I don't use spring I can't very
> easily contribute. I'm happy to look at an extension project for
> inclusion if someone comes up with one.
>

daen

unread,
Jan 3, 2011, 4:59:56 PM1/3/11
to Morphia
Sonar,
I use the following Spring config and it works fine for me:

<bean id="mongo" class="com.mongodb.Mongo">
<constructor-arg value="localhost"/>
<constructor-arg value="27017"/>
</bean>

<bean id="morphia" class="com.google.code.morphia.Morphia"/>

<bean id="datastore" factory-bean="morphia" factory-
method="createDatastore">
<constructor-arg ref="mongo"/>
<constructor-arg value="novalumen"/>
</bean>

<bean class="com.google.code.morphia.dao.BasicDAO">
<qualifier value="my"/>
<constructor-arg value="com.mycompany.My" type="java.lang.Class"/
>
<constructor-arg ref="datastore"/>
</bean>

In the code I do the following:
import com.google.code.morphia.dao.DAO;

class MyService {
@Autowired
@Qualifier("my")
private DAO<My, ObjectId> dao;
}

When I do need more methods than Morphia's DAO interface offers, I
extend Morphia's BasicDAO and leave only those constructors that are
relevant to my use case, e.g.:

import com.google.code.morphia.dao.BasicDAO;

class CustomDaoImpl extends BasicDAO<CustomClass, ObjectId> implements
CustomDao {
public CustomDaoImpl(Datastore ds) {
super(CustomClass.class, ds);
}


Of course, this approach doesn't minimize the number of constructor
parameters, but I found it pretty lightweight and I keep all declared
DAOs in a separate config file. When the number of DAOs declarations
will grow, I'll come up with better approach how to declare them. One
idea is to use custom annotation in my code and create a DAO instance
on Spring context initialization using information from the annotated-
class.

Hope it helps.

Thanks,
Dmytro.

Scott Hernandez

unread,
Jan 3, 2011, 5:17:12 PM1/3/11
to mor...@googlegroups.com
Thanks for the example... I was pretty sure it was that simple.

Just out of curiosity, how do you mark those as singletons?

Sonar

unread,
Jan 3, 2011, 5:34:29 PM1/3/11
to Morphia
Daen,

Again, you need to have all daos declared in the app context, I hate
doing that (and I don't have to, @Repository worked perfectly for me
so far)... And instead of going down the path with custom annotations
and stuff suggected by you, I kindly ask Morphia team to add TWO lines
of code into BasicDao for me. Kinda funny, don't you think?

Alexey


On Jan 3, 5:17 pm, Scott Hernandez <scotthernan...@gmail.com> wrote:
> Thanks for the example... I was pretty sure it was that simple.
>
> Just out of curiosity, how do you mark those as singletons?
>

daen

unread,
Jan 3, 2011, 6:07:29 PM1/3/11
to Morphia
They are singletons by default. You can change that beans with 'scope'
attribute, like:
<bean class="com.MyDao" scope="prototype"/>

daen

unread,
Jan 3, 2011, 6:28:09 PM1/3/11
to Morphia
Sonar,
you're saying you have a dozen of BasicDao subclasses and you don't
want to declare them in Spring config. If this is the case, let me
illustrate how you can apply @Repository annotation (I think that't
what you'd like to do):

(I'm repeating some of my previous code)

In you Spring config:

<bean id="mongo" class="com.mongodb.Mongo">
<constructor-arg value="localhost"/>
<constructor-arg value="27017"/>
</bean>

<bean id="morphia" class="com.google.code.morphia.Morphia"/>

<bean id="datastore" factory-bean="morphia" factory-
method="createDatastore">
<constructor-arg ref="mongo"/>
<constructor-arg value="my-db-name"/>
</bean>


My custom DAO interface:

interface CustomDao extends DAO<MyBean, String> {
//custom DAO methods
}

My BasicDAO subclass:

@Repository
public class CustomDaoImpl extends BasicDAO<MyBean, String> implements
CustomDao {
@Autowired
public CustomDaoImpl(Datastore ds) {
super(MyBean.class, ds);
}

// no other constructors needed

// CustomDao's methods implementation
}

In my service class:

@Service
public class MyServiceImpl {

@Autowired
private CustomDao dao;

// other service methods
}

As you see besides declaring Mongo, Morphia and Datastore no DAO beans
declared in XML.

Thanks.

Sonar

unread,
Jan 3, 2011, 9:38:55 PM1/3/11
to Morphia
Well, at least this can solve one issue out of two.. Thank a lot, the
idea to use Autowired on constructor is really nice.
Reply all
Reply to author
Forward
0 new messages