Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Polymorphism for spring data?

  1. #1
    Join Date
    Aug 2005
    Location
    Cincinnati
    Posts
    17

    Default Polymorphism for spring data?

    Does spring-data support polymorphism? For example, can persist a concrete implementation using a repository declared to manage the interface?

    Code:
    public interface Artifact 
    {
       ObjectId getId();   
       String getArtifactName();
       String getArtifactType();
       List<String> getSupportedModels();
       Date getDateAdded(); 
       File getArtifactFile();
       
    }
    
    public abstract class AbstractArtifact implements Artifact
    {
    ...
    }
    
    public class ConcreteArtifact extends AbstractArtifact 
    {
    ....
    }
    
    public interface ArtifactRepository extends MongoRepository<Artifact,ObjectId> {}

    I seem to be able to instantiate a ConcreteArtifact and save it fine. The mongo shell depicts all attributes using find(). However, when I attempt to use the findOne() method on the ArtifactRepository I receive the following error:

    Code:
    org.springframework.data.mapping.model.MappingInstantiationException: Could not instantiate bean class [com.lexmark.pssd.app.mve.library.Artifact]: Specified class is an interface at 
    org.springframework.data.mapping.MappingBeanHelper.constructInstance(MappingBeanHelper.java:115) at  
    org.springframework.data.document.mongodb.convert.MappingMongoConverter.read(MappingMongoConverter.java:214) at
     org.springframework.data.document.mongodb.convert.MappingMongoConverter.read(MappingMongoConverter.java:199) at
     org.springframework.data.document.mongodb.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:1480) at
     org.springframework.data.document.mongodb.MongoTemplate.execute(MongoTemplate.java:337) at 
    org.springframework.data.document.mongodb.MongoTemplate.doFindOne(MongoTemplate.java:978) at
     org.springframework.data.document.mongodb.MongoTemplate.findOne(MongoTemplate.java:485) at
     org.springframework.data.document.mongodb.MongoTemplate.findOne(MongoTemplate.java:480) at
     org.springframework.data.document.mongodb.repository.SimpleMongoRepository.findOne(SimpleMongoRepository.java:99) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
     sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.data.repository.support.RepositoryFactorySupport$QueryExecuterMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:355) at org.springframework.data.repository.support.RepositoryFactorySupport$QueryExecuterMethodInterceptor.invoke(RepositoryFactorySupport.java:336) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at
     org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy123.findOne(Unknown Source) at com.lexmark.pssd.app.mve.library.ArtifactRepositoryIntegrationTest.testSave(ArtifactRepositoryIntegrationTest.java:61) at

  2. #2

    Default

    Have you tried to pass the Class object of the concrete implementation as fondOne() argument as it is in the documentation?

    Code:
    .findOne(new Query(Criteria.where("name").is("Joe")), Person.class)

  3. #3
    Join Date
    Aug 2005
    Location
    Cincinnati
    Posts
    17

    Default

    Well...I'm pretty sure that will work. What I really want is to place different concrete implementations into the same collection and be able to query them. For example, if ConcreteA and ConcreteB are both persisted into the same collection, then I want to be able to query for all objects in the collection and know that each is materialized appropriately.

    In sum, I want to be able to save a discriminator (maybe the @Document type?) along with the object and have the Repository use that information to instantiate the correct implementation upon query.

  4. #4
    Join Date
    Apr 2006
    Location
    Dresden, Germany
    Posts
    483

    Default

    Currently we unfortunately don't. As Matthias has pointed out you can be specific on the class you're querying for on the template level (and thus map data to various classes by just piping in a different type). Currently the repositories uses the domain type you type the repo to (Account in your case) to map the returned data to it. That's the only way it works right now as we do not transparently store concrete type information for root documents (we already do for nested ones). Unfortunately there won't be no general solution as on storing at the template you simply pipe in an object and we don't know you might use it behind an interface.

    However, we could let the repository save infrastructure store the concrete type in the document in case the repository is managing an interface or an abstract class. Could you please open a JIRA for that and assign it to the repository component. I will have a look at it ASAP then.

    Cheers,
    Ollie

  5. #5
    Join Date
    Aug 2005
    Location
    Cincinnati
    Posts
    17

    Default

    Thanks for the information Oliver. I will open a JIRA ticket today.

    Given this information, it would seem that a good rule of thumb for spring data would be a single domain class per collection. I had also thought that I might be able to query "across" collections as a workaround, but don't see that type of functionality either.

  6. #6
    Join Date
    Apr 2006
    Location
    Dresden, Germany
    Posts
    483

    Default

    We already do entity-per-collection. Or to be more precise, one collection for the entity the repository is typed to. I think this makes much sense as document databases work quite nicely with slightly differently shaped data. Plus we can do polymorphic queries quite easily.

  7. #7
    Join Date
    Aug 2005
    Location
    Cincinnati
    Posts
    17

    Default

    Not sure what you mean by "polymorphic" queries in the last response. Isn't that what we're suggesting should be implemented by the new JIRA issue?

    JIRA issue for this thread: https://jira.springsource.org/browse/DATADOC-128

    Thanks!

  8. #8
    Join Date
    Apr 2006
    Location
    Dresden, Germany
    Posts
    483

    Default

    Polymorphic in that context means that you potentially get back objects of different types. Mostly they are in some kind of type hierarchy. If every concrete type would get it's own collection then we'd have to query the collections separately which is not only slow but also rather tricky to handle when using pagination and the like.

  9. #9
    Join Date
    May 2011
    Posts
    4

    Default

    Im using spring-data-mongodb.1.0.0.M2. Ive defined my mongorepository as

    @Transactional
    public interface UserRepository extends MongoRepository<User,String>{

    }
    ----------
    And then make hte following call.

    List<User> allUsers = userRepository.findAll();
    ----------------------
    I'm getting the following error.

    org.springframework.beans.BeanInstantiationExcepti on: Could not instantiate bean class [java.util.List]: Specified class is an interface
    at org.springframework.beans.BeanUtils.instantiateCla ss(BeanUtils.java:101)
    at org.springframework.data.document.mongodb.convert. SimpleMongoConverter.read(SimpleMongoConverter.jav a:346)
    at org.springframework.data.document.mongodb.convert. SimpleMongoConverter.readMap(SimpleMongoConverter. java:456)
    at org.springframework.data.document.mongodb.convert. SimpleMongoConverter.readCompoundValue(SimpleMongo Converter.java:427)
    at org.springframework.data.document.mongodb.convert. SimpleMongoConverter.read(SimpleMongoConverter.jav a:361)
    at org.springframework.data.document.mongodb.MongoTem plate$ReadDbObjectCallback.doWith(MongoTemplate.ja va:1480)
    at org.springframework.data.document.mongodb.MongoTem plate.executeEach(MongoTemplate.java:371)
    at org.springframework.data.document.mongodb.MongoTem plate.doFind(MongoTemplate.java:1006)
    at org.springframework.data.document.mongodb.MongoTem plate.find(MongoTemplate.java:522)
    at org.springframework.data.document.mongodb.reposito ry.SimpleMongoRepository.findAll(SimpleMongoReposi tory.java:231)
    at org.springframework.data.document.mongodb.reposito ry.SimpleMongoRepository.findAll(SimpleMongoReposi tory.java:173)
    at org.springframework.data.document.mongodb.reposito ry.SimpleMongoRepository.findAll(SimpleMongoReposi tory.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.data.repository.support.Reposi toryFactorySupport$QueryExecuterMethodInterceptor. executeMethodOn(RepositoryFactorySupport.java:355)
    at org.springframework.data.repository.support.Reposi toryFactorySupport$QueryExecuterMethodInterceptor. invoke(RepositoryFactorySupport.java:336)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :172)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:202)

    ----------

    What is wrong here?

    Thanks in advance.

  10. #10

    Default

    1. Why are you adding a @Transactional Annotation? MongoDB does not support Transactions.
    Only Atomic Operations are supported. See http://www.mongodb.org/display/DOCS/...s%2Flocking%3F

    2. You are still using SimpleMongoConverter, which is Deprecated!
    Add

    <mongo:mapping-converter id="converter" />

    and <constructor-arg ref="converter" />

    to the MongoTemplate constructor arguments

    to your beans.xml to use the MappingMongoConverter (or instanceiate it by using the bean tag)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •