Spring Data MongoDB
  1. Spring Data MongoDB
  2. DATAMONGO-179

MongoDB Lifecycle events not being initialized

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Works as Designed
    • Affects Version/s: 1.0 M3
    • Fix Version/s: None
    • Component/s: Mapping
    • Labels:
      None

      Description

      After I register:

      <bean class="com.xxx.event.OnAfterConvertUserEventListener"/>
      

      I would expect the below method userRepository.findByUsername to initiate the aforementioned bean. It doesn't. In the docs, it says that if I use findOne(), it will pick it up.

      It does work when I call userRepository.findAll().

      @Repository("userRepository")
      public class MongoUserRepository extends QueryDslMongoRepository<User, String> implements UserRepository {
          QUser user = QUser.user;
      
          @Autowired
          public MongoUserRepository(MongoTemplate mongoTemplate) {
              super(new MappingMongoEntityInformation<User, String>(
                      new BasicMongoPersistentEntity<User>(
                              new ClassTypeInformation<User>(User.class))
              ), mongoTemplate
              );
          }
      
          @Override
          public User findByUsername(String username) {
              return findOne(user.username.eq(username));
          }
      }
      

        Activity

        Hide
        Bjorn Harvold added a comment -

        public interface UserRepository extends PagingAndSortingRepository<User, String>, QueryDslPredicateExecutor<User>

        { User findByUsername(String username); }
        Show
        Bjorn Harvold added a comment - public interface UserRepository extends PagingAndSortingRepository<User, String>, QueryDslPredicateExecutor<User> { User findByUsername(String username); }
        Hide
        Bjorn Harvold added a comment -

        It does work if I do not implement my own Repository but instead use <mongo:repositories base-package="com.xxxx.repository"/>. I am guessing right now there is no middle ground when I want to use QueryDsl.

        Show
        Bjorn Harvold added a comment - It does work if I do not implement my own Repository but instead use <mongo:repositories base-package="com.xxxx.repository"/>. I am guessing right now there is no middle ground when I want to use QueryDsl.
        Hide
        Oliver Gierke added a comment -

        Regarding you're architectural question extending QueryDslMongoRepository is not the way to go. Prefer adding a custom implementation the way it is described in the reference documentation. Using QueryDslRepositorySupport as base class provides convenientce methods for accessing Querydsl artifacts.

        What does your OnAfterConvertUserEventListener?

        Show
        Oliver Gierke added a comment - Regarding you're architectural question extending QueryDslMongoRepository is not the way to go. Prefer adding a custom implementation the way it is described in the reference documentation . Using QueryDslRepositorySupport as base class provides convenientce methods for accessing Querydsl artifacts. What does your OnAfterConvertUserEventListener ?
        Hide
        Bjorn Harvold added a comment -

        Please resolve. This is no longer an issue. I failed to follow instructions properly.

        Cheers
        bjorn

        Show
        Bjorn Harvold added a comment - Please resolve. This is no longer an issue. I failed to follow instructions properly. Cheers bjorn
        Hide
        Oliver Gierke added a comment -

        Great to hear Bjorn! You might want to watch DATAMONGO-170 which deals with the approachability of the event listeners in general. Does the recommendation regarding your general approach make sense?

        Show
        Oliver Gierke added a comment - Great to hear Bjorn! You might want to watch DATAMONGO-170 which deals with the approachability of the event listeners in general. Does the recommendation regarding your general approach make sense?
        Hide
        Bjorn Harvold added a comment -

        Yes it makes sense. I was actually thinking about using the listeners as a way to inject/cache reference data. So instead of using @DbRef, which is going to be deprecated anyway according to the MongoDb team, I'll just use the ObjectId.

        Example:
        User.java
        --> Has a list of Roles

        I don't want to embed these global roles (e.g. System Admin), So I link the ObjectIds instead. Roles is also something I want to cache on the server. When a user logs in, I need to "enrich" the user with the role objects that I put in the spring security context. The listener, then, should ,onAfterConvert of User, look first in the cache to see if it can find the roles. If it can't find it, it loads it from mongo, sticks it in the cache and adds it to the user. This "enrichment" process might not be necessary for all calls to load user either.

        The problem is I cannot inject any other mongo repositories into the listener as the repositories haven't been created yet. So I basically had to stop using the listener and do it manually.

        I think using the listeners in such a way would be pretty useful for people.

        Cheers
        bjorn

        Show
        Bjorn Harvold added a comment - Yes it makes sense. I was actually thinking about using the listeners as a way to inject/cache reference data. So instead of using @DbRef, which is going to be deprecated anyway according to the MongoDb team, I'll just use the ObjectId. Example: User.java --> Has a list of Roles I don't want to embed these global roles (e.g. System Admin), So I link the ObjectIds instead. Roles is also something I want to cache on the server. When a user logs in, I need to "enrich" the user with the role objects that I put in the spring security context. The listener, then, should ,onAfterConvert of User, look first in the cache to see if it can find the roles. If it can't find it, it loads it from mongo, sticks it in the cache and adds it to the user. This "enrichment" process might not be necessary for all calls to load user either. The problem is I cannot inject any other mongo repositories into the listener as the repositories haven't been created yet. So I basically had to stop using the listener and do it manually. I think using the listeners in such a way would be pretty useful for people. Cheers bjorn
        Hide
        Oliver Gierke added a comment -

        You actually should be able to do so. Even if using setter injection (Spring then defers initialization and wiring until all dependencies are available to some degree) does not work you might wanna try configuring a LazyInitTargetSource as intermediate proxy. This way Spring will be able to create the listener instance without already creating the repository instance. The repo proxy will be created on very first access then.

        Show
        Oliver Gierke added a comment - You actually should be able to do so. Even if using setter injection (Spring then defers initialization and wiring until all dependencies are available to some degree) does not work you might wanna try configuring a LazyInitTargetSource as intermediate proxy. This way Spring will be able to create the listener instance without already creating the repository instance. The repo proxy will be created on very first access then.
        Hide
        Bjorn Harvold added a comment -

        You are right. Setter injection works just fine.

        Show
        Bjorn Harvold added a comment - You are right. Setter injection works just fine.

          People

          • Assignee:
            Oliver Gierke
            Reporter:
            Bjorn Harvold
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: