1
votes

I have a Service class as below which I deployed using Maven and is Active on Sling Web Console. When I am accessing the method getSearchAssetNames() from this bundle it is getting called as per the AEM 6.0 logs on Authoring instance.

But, implicit objects such as repository, resource resolver factory, query builder are all getting null pointer exceptions through how I have derived them using @Reference annotation.

Here is the code for the class. I have tried removing activate, deactivate methods, adding start/stop methods, everything, but still this does not work.

Error logs show:

*01.07.2015 12:05:24.014 INFO [127.0.0.1 [1435732523998] GET /content/test/en/headerfooter/jcr:content/footerpar/testassetfinder..html HTTP/1.1] com.test.example.assetfinder.AssetFinderImpl Query Builder: null 01.07.2015 12:05:24.014 INFO [127.0.0.1 [1435732523998] GET /content/test/en/fordheaderfooter/jcr:content/footerpar/testassetfinder..html HTTP/1.1] com.test.example.assetfinder.AssetFinderImpl JCR Repository: null Caused by: java.lang.NullPointerException: null at com.test.example.assetfinder.AssetFinderImpl.getSearchAssetNames(AssetFinderImpl.java:61)*

Can anyone please help me regarding how to solve this ?

            package com.test.example.assetfinder;

            import java.util.ArrayList;
            import java.util.HashMap;
            import java.util.List;
            import java.util.Map;

            import javax.jcr.RepositoryException;
            import javax.jcr.Session;

            import org.apache.felix.scr.annotations.Activate;
            import org.apache.felix.scr.annotations.Component;
            import org.apache.felix.scr.annotations.Deactivate;
            import org.apache.felix.scr.annotations.Reference;
            import org.apache.felix.scr.annotations.Service;
            import org.apache.sling.jcr.api.SlingRepository;
            import org.osgi.service.component.ComponentContext;
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            import com.day.cq.search.PredicateGroup;
            import com.day.cq.search.Query;
            import com.day.cq.search.QueryBuilder;
            import com.day.cq.search.result.Hit;
            import com.day.cq.search.result.SearchResult;


            /**
             * Example Asset Finder in AEM DAM.
             */
            @Service(value=com.test.example.assetfinder.AssetFinderService.class)
            @Component
            public class AssetFinderImpl implements AssetFinderService {

                @Reference
                private QueryBuilder builder;

                @Reference
                private ResourceResolverFactory resolverFactory;

                @Reference
                private SlingRepository repository;

                private static final Logger LOGGER = LoggerFactory.getLogger(AssetFinderImpl.class);

                @Activate
                protected void activate(final ComponentContext pCtx) throws RepositoryException {
                }
                @Deactivate
                protected void deactivate(ComponentContext pCtx) throws RepositoryException {
                }

                public List<String> getSearchAssetNames() {
                    List<String> assetList = new ArrayList<String>();
                    Session session = null;
                    try {
                        LOGGER.info("Query Builder: "  +builder);
                        LOGGER.info("Resolver Factory: "  +resolverFactory);
                        LOGGER.info("JCR Repository: " +repository);

                        session = repository.loginAdministrative(null);           
                        Map<String, String> map = new HashMap<String, String>();
                        map.put("path",         "/content/dam");
                        map.put("type",         "dam:Asset");
                        map.put("nodename",     "*example*.*");
                        map.put("orderby.sort", "asc");           
                        Query query = builder.createQuery(PredicateGroup.create(map), session);
                        SearchResult result = query.getResult();

                        // Iterating over the results
                        for (Hit hit : result.getHits()) {
                            assetList.add(hit.getTitle());
                        }
                    } catch(RepositoryException re) {
                        re.printStackTrace();       
                    } finally {
                        if(null != session) {
                            session.logout();
                        }
                    }       
                    return assetList;
                }
            }
1
They changed a few things with AEM 6. Have a look at this blog post: wemblog.com/2014/08/how-to-use-sessions-and-resource.htmlThomas
Hi Thomas, thanks for your time and suggestions ! I tried to update the dependency on the bundle pom xml like this: ` <dependency> <groupId>com.adobe.aem</groupId> <artifactId>aem-api</artifactId> <version>6.0.0.1</version> <scope>provided</scope> </dependency> ` and then tried to clean build. But it is not taking the updated methods that look error free on eclipse which have the aem-api-6.0.0.1 jar in its classpath. Any clues ?Somnath Mookerjee
I resolved the maven build issue with dependency fix. However, when I build the bundle, resolverFactory is still null - the harsh reality, no escaping from that one ! On the whole: @Reference private ResourceResolverFactory resolverFactory; is not working for me.Somnath Mookerjee
That is indeed strange. Do you have some unsatisified bundles in your OSGi console? Your service shouldn't even start if he Referenced service isn't available. Maybe try to add the following annotation property: @Reference(policy = ReferencePolicy.STATIC)Thomas
The issue has been resolved. Following are my lessons learned: 1. From component JSP the call to OSGi Service has to be done using Serive-class-name service-object = sling.getService("service-class-name.class"); and not using normal instantiation new operator. 2. @Activate annotation is not required in the impl class. Since it is implementing an interface, @Override is good. 3. While declaring maven dependencies, I faced build error while including aem 6.0.0.1. I removed the previous version dependency for importing ResourceResolverFactory class and the maven build error went away.Somnath Mookerjee

1 Answers

2
votes

The key thing here is that when you use @Reference, that injects a service reference into an instance of your class managed by the Service Component Runtime (SCR) and only into that managed instance. If you create a new (i.e. different) instance of your class, then it won't have the field injected. Which is why you need to use the sling.getService() method to get the managed instance.

A best practice is to avoid having the implementation class be in an exported package. That way, you can't reference the implementation class directly from a JSP; you can only reference the service interface so you could never create a new instance from the JSP and thus not hit the problem of using a non-managed instance of the class.

Regarding @Activate and @Deactivate, you would need those only if your activate/deactivate methods did anything. In this case, they don't (at least in your code example). You can also get away from using them if you name your methods activate and deactivate, but personally I would always recommend using them just to be on the safe side, e.g. if you mistype the name as activte or something like that.