PDA

View Full Version : Custom repository functionality



vguna
Sep 11th, 2011, 03:57 PM
Hi.

I'm trying to implement custom repository functionality with the spring-data-mongodb M3. I followed the documentation that says:

- Create a simple interface with your custom method
- Create a simple implementation of the interface
- Let your repository interface also extend simple interface, not just CrudRepository

So my custom method should be acessible in addition to the standard CRUD operations containing my hand written code.
But when I start my application, spring tries to build a query from my custom methods' name - and fails of course:



Caused by: java.lang.IllegalArgumentException: No property find found for type class my.domain.FooObject
at org.springframework.data.repository.query.parser.P roperty.<init>(Property.java:66)
at org.springframework.data.repository.query.parser.P roperty.<init>(Property.java:100)
at org.springframework.data.repository.query.parser.P roperty.create(Property.java:300)
at org.springframework.data.repository.query.parser.P roperty.create(Property.java:314)
at org.springframework.data.repository.query.parser.P roperty.create(Property.java:280)
at org.springframework.data.repository.query.parser.P roperty.from(Property.java:239)
at org.springframework.data.repository.query.parser.P roperty.from(Property.java:227)
at org.springframework.data.repository.query.parser.P art.<init>(Part.java:48)
at org.springframework.data.repository.query.parser.P artTree$OrPart.<init>(PartTree.java:242)
at org.springframework.data.repository.query.parser.P artTree.buildTree(PartTree.java:101)
at org.springframework.data.repository.query.parser.P artTree.<init>(PartTree.java:77)
at org.springframework.data.document.mongodb.reposito ry.PartTreeMongoQuery.<init>(PartTreeMongoQuery.java:42)
at org.springframework.data.document.mongodb.reposito ry.MongoRepositoryFactoryBean$MongoRepositoryFacto ry$MongoQueryLookupStrategy.resolveQuery(MongoRepo sitoryFactoryBean.java:203)
at org.springframework.data.repository.support.Reposi toryFactorySupport$QueryExecuterMethodInterceptor.<init>(RepositoryFactorySupport.java:290)


My custom method is called findAll(some, parameters, I, defined, myself, and, Pageable);

So it seems to use the algorithm for auto-generated-query-by-method. But instead it should simply call my custom method on my implementation.

Has anyone an idea why is that?

vguna
Sep 11th, 2011, 04:30 PM
Ok, couldn't leave my fingers off that :). So I got it working with:



<repositories base-package="my.dao.package">
<repository id="accountDao" custom-impl-ref="customAccountDaoImpl" />
<repository id="userDao"/>
<repository id="personDao"/>
</repositories>

<beans:bean id="customAccountDaoImpl" class="my.package.CustomAccountDaoImpl" />


So it seems that I have to explicitly name all DAOs that I'm using when specifying a custom impl. Only specifying the custom repository doesn't work. Then an exception 'No bean 'userDao' exists' is thrown.
Without using a custom repository impl just:



<repositories base-package="my.dao.package">


seems sufficient though.

Oliver Gierke
Sep 12th, 2011, 05:08 AM
I think you stumble over the fact that we lookup the implementation interface and class in the very same package of the original repository interface. If you place all into one you should be fine. A second approach should be naming the implementaion bean accountDaoImpl as we check for an existing bean matching the "repository name + postfix" pattern before registering a bean definition for a potentially found class. This should enable you to get rid of the manual repository configuration.

The manual configuration was initially designed for users with the need for very fine grained control and currently pretty much disables automatic lookups entirely. We were thinking about changing that to still do automatic configuration but taking explicitly defined repository beans into account 8so pretty much the way you initially expected it to work). If you think that's the more convenient approach feel free to raise a JIRA ticket.

vguna
Sep 12th, 2011, 01:04 PM
I think you stumble over the fact that we lookup the implementation interface and class in the very same package of the original repository interface. If you place all into one you should be fine. A second approach should be naming the implementaion bean accountDaoImpl as we check for an existing bean matching the "repository name + postfix" pattern before registering a bean definition for a potentially found class. This should enable you to get rid of the manual repository configuration.

I can confirm, both of your suggested ways work. The problem was, I named my file DAO instead of Dao hence the problem I guess. Heard that those algorithms begin to struggle with these kind of namings. I simply changed it to Dao and now
it works like you've described it.

Thanks!

nicklasholm
Feb 16th, 2012, 07:15 AM
I think you stumble over the fact that we lookup the implementation interface and class in the very same package of the original repository interface. If you place all into one you should be fine. A second approach should be naming the implementaion bean accountDaoImpl as we check for an existing bean matching the "repository name + postfix" pattern before registering a bean definition for a potentially found class. This should enable you to get rid of the manual repository configuration.

I believe I have followed the first approach to the letter and read the reference document (see link bellow) over and over, but I still get the same error as vguna.

http://static.springsource.org/spring-data/data-jpa/docs/1.0.3.RELEASE/reference/html/#repositories.single-repository-behaviour


I have the following files all in the same folder:

RepresentativeRepository


public interface RepresentativeRepository extends JpaRepository<Representative, Integer>, RepresentativeRepositoryCustom {

@Override
List<Representative> doStuff();
}


RepresentativeRepositoryCustom


public interface RepresentativeRepositoryCustom {

List<Representative> doStuff();
}


RepresentativeRepositoryImpl


public class RepresentativeRepositoryImpl implements RepresentativeRepositoryCustom {

@PersistenceContext
private EntityManager entityManager;

@Override
public List<Representative> doStuff() {
Query query = entityManager.createQuery("my query...");
return query.getResultList();
}
}

revengeofthepencil
Sep 27th, 2012, 12:41 PM
I'm stuck in exact;y the same place. Did you ever figure this out?

Thanks,
Alex

Oliver Gierke
Sep 27th, 2012, 12:54 PM
Try removing the doStuff() method declaration from the RepresentativeRepository interface (although that shouldn't cause the error). What exceptions are you guys seeing? You might wanna have a look at the examples repo which has a sceneario like this implemented at [0].

[0] https://github.com/SpringSource/spring-data-jpa-examples/tree/master/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository

ohagangt
Dec 7th, 2012, 09:56 AM
Hi vguna,

I am experiencing the same issue as you but I am not sure if a have the full picture in terms of implementation. Can you please provide an implementation of how this is done.


Gary




Ok, couldn't leave my fingers off that :). So I got it working with:



<repositories base-package="my.dao.package">
<repository id="accountDao" custom-impl-ref="customAccountDaoImpl" />
<repository id="userDao"/>
<repository id="personDao"/>
</repositories>

<beans:bean id="customAccountDaoImpl" class="my.package.CustomAccountDaoImpl" />


So it seems that I have to explicitly name all DAOs that I'm using when specifying a custom impl. Only specifying the custom repository doesn't work. Then an exception 'No bean 'userDao' exists' is thrown.
Without using a custom repository impl just:



<repositories base-package="my.dao.package">


seems sufficient though.