Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-47371

Calling getContact() on a User object in an IndexerPostProcessor postProcessDocument method throws NoSuchContactException

    Details

      Description

      Steps to reproduce

      === A.) Within the portal

      1- Modify the constructor of UserIndexer to look like this:

      UserIndexer.java
      	public UserIndexer() {
      		setDefaultSelectedFieldNames(
      			Field.COMPANY_ID, Field.UID, Field.USER_ID);
      		setIndexerEnabled(PropsValues.USERS_INDEXER_ENABLED);
      		setPermissionAware(true);
      		setStagingAware(false);
      
      		IndexerPostProcessor userIndexerPostProcessor =
      			new BaseIndexerPostProcessor() {
      
      			@Override
      			public void postProcessDocument(Document document, Object obj)
      				throws Exception {
      
      				User user = (User)obj;
      
      				System.out.println(user.getContact().getFirstName());
      
      				Group group = user.getGroup();
      
      				System.out.println(group.getFriendlyURL());
      			}
      
      		};
      
      		registerIndexerPostProcessor(userIndexerPostProcessor);
      	}
      

      2- Build (or just run "ant deploy" from portal-impl)
      3- Start portal on clean a DB or just add a new user

      Result: NoSuchContactException occurs

      Caused by: com.liferay.portal.NoSuchContactException: No Contact exists with the primary key 11002
      	at com.liferay.portal.service.persistence.impl.ContactPersistenceImpl.findByPrimaryKey(ContactPersistenceImpl.java:1895)
      	at com.liferay.portal.service.persistence.impl.ContactPersistenceImpl.findByPrimaryKey(ContactPersistenceImpl.java:1912)
      	at com.liferay.portal.service.base.ContactLocalServiceBaseImpl.getContact(ContactLocalServiceBaseImpl.java:225)
      	at sun.reflect.GeneratedMethodAccessor269.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      	at java.lang.reflect.Method.invoke(Unknown Source)
      	at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:115)
      	at com.liferay.portal.spring.transaction.DefaultTransactionExecutor.execute(DefaultTransactionExecutor.java:62)
      	at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:55)
      	at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111)
      	at com.liferay.portal.spring.aop.ServiceBeanAopProxy.invoke(ServiceBeanAopProxy.java:175)
      	at com.sun.proxy.$Proxy28.getContact(Unknown Source)
      	at com.liferay.portal.service.ContactLocalServiceUtil.getContact(ContactLocalServiceUtil.java:186)
      	at com.liferay.portal.model.impl.UserImpl.getContact(UserImpl.java:161)
      

      Note You would get NoSuchGroupException if you removed the "getContact()" call from the code.

      Expected result: There should be no exception.

      === 2.) By a hook

      Implementing IndexerPostProcessor hook has some implications.

      If I add user then the indexer event will be fired 3 times. At first postProcessDocument(..) callthe user.getContact() is throwing NoSuchContactException exception. -> PROBLEM

      Second and Third time the contact is working.

      The developer should be able to trust our API that is working properly.

      This can be easily tested by creating IndexerPostProcessor

      public class UserContactIndexerPostProcessor implements IndexerPostProcessor {
      	@Override
      	public void postProcessDocument(Document document, Object object) throws Exception {
      		User user = (User)object;
      		System.out.println(user.getContact().getFirstName());
      	}
      	@Override
      	public void postProcessContextQuery(BooleanQuery arg0, SearchContext arg1) throws Exception {}
      	@Override
      	public void postProcessFullQuery(BooleanQuery arg0, SearchContext arg1) throws Exception {}
      	@Override
      	public void postProcessSearchQuery(BooleanQuery arg0, SearchContext arg1) throws Exception {}
      	@Override
      	public void postProcessSummary(Summary arg0, Document arg1, Locale arg2, String arg3, PortletURL arg4) {}
      }
      

      This behavior happens due adding resources to user at UserLocalServiceImpl

      		resourceLocalService.addResources(
      			companyId, 0, creatorUserId, User.class.getName(), user.getUserId(),
      			false, false, false);
      

      I would consider to prevent indexing this point, if the entity will be indexed anyways.

      Further consideration with this fix it could be also reasonable to fix that user indexer is not called twice at UserService level and again at UserLocalService level.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Due:
                  Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  5 years, 20 weeks, 4 days ago

                  Packages

                  Version Package
                  6.2.2 CE GA3
                  6.2.X EE
                  7.0.0 M1