Expand my Community achievements bar.

SOLVED

LoginException: Cannot derive user name for bundle (Service Resolver Issue)

Avatar

Level 5

Platform Version: AEM 6.2

Something I've noticed after using the service resolver pattern for a few months now, is that unless my class is a @Service and can @Reference the ResourceResolverFactory, then anytime I try to get a service resolver, I get the following error:

org.apache.sling.api.resource.LoginException: Cannot derive user name for bundle org.apache.sling.api [64] and sub service ugc-writer at org.apache.sling.resourceresolver.impl.ResourceResolverFactoryImpl.getServiceResourceResolver(ResourceResolverFactoryImpl.java:83)

Example class:

package org.testing.temp; import com.day.cq.wcm.api.Page; import org.apache.commons.lang.StringUtils; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.api.scripting.SlingScriptHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class TempFunctions { private static final Logger LOG = LoggerFactory.getLogger(TempFunctions.class); private TempFunctions() { /* Static methods only - no instances */ } public static final String getSomeString(final SlingScriptHelper sling, final Page page) { final ResourceResolverFactory resourceResolverFactory = sling.getService(ResourceResolverFactory.class); Map<String, Object> serviceParams = new HashMap<>(); serviceParams.put(ResourceResolverFactory.SUBSERVICE, "ugc-writer"); try (ResourceResolver serviceResolver = resourceResolverFactory.getServiceResourceResolver(serviceParams)) { // do something with the service resolver here... } catch (LoginException e) { LOG.error("LoginException: {}", e); } return StringUtils.EMPTY; } }

Example of how I'm calling this code, a JSTL taglib function called within the JSP:

<%@include file="/libs/foundation/global.jsp"%> <c:set var="tempString" value="${ testingTemp:getSomeString(sling, resourcePage) }" /> <div>${ tempString }</div>

It's like, despite the call originating from my bundle, it's using the org.apache.sling.api bundle context and so the service mapper that I configured with my bundle is completely ignored. Has anyone else encountered this?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Would not assume so, @Service is just an annotation, behind the scenes SCR xml get's saved into OSGi/SCR service resolution mappings system which is fairly transparent and fast. Calling Service method itself is lighting fast(write simple Apache Felix test to see this yourself). What gives it time is the logic that you put in body of the method call.

Regards,

Peter

View solution in original post

8 Replies

Avatar

Level 5

I can get this working without log errors if I retrieve the ResourceResolverFactory from from the FrameworkUtil[1] class instead of from the SlingScriptHelper interface, essentially forcing the BundleContext to my class' bundle, instead of the Sling API bundle.

// get the ResourceResolverFactory directly from your own bundle. BundleContext bundleContext = FrameworkUtil.getBundle(TempFunctions.class).getBundleContext(); ServiceReference factoryRef = bundleContext.getServiceReference(ResourceResolverFactory.class.getName()); ResourceResolverFactory resourceResolverFactory = (ResourceResolverFactory) bundleContext.getService(factoryRef);

Seems like I shouldn't have to do this though, am I wrong?

[1] https://osgi.org/javadoc/r4v43/core/org/osgi/framework/FrameworkUtil.html

Avatar

Community Advisor

Apologies if I don't understand something in your question,

Why not define an API where each user write action is Service function with it's own logic and related references? This AWESOME feature is available in 6.2 !!! [1]

Then, you would not need to do this OSGi framework level magic(even through ThreadSafe).

As per OSGi the reason why it provides Service and Reference annotations, is to take care of the more complicated stuff, which you are trying to solve here(which they solved btw).

Don't you feel like having a lot of inline Java functions embedded in the Sightly code make it harder to maintain?

[1] https://issues.apache.org/jira/browse/SLING-4554

Regards,

Peter

Avatar

Level 5

PuzanovsP wrote...

Apologies if I don't understand something in your question,

Why not define an API where each user write action is Service function with it's own logic and related references? This AWESOME feature is available in 6.2 !!! [1]

Then, you would not need to do this OSGi framework level magic(even through ThreadSafe).

As per OSGi the reason why it provides Service and Reference annotations, is to take care of the more complicated stuff, which you are trying to solve here(which they solved btw).

Don't you feel like having a lot of inline Java functions embedded in the Sightly code make it harder to maintain?

[1] https://issues.apache.org/jira/browse/SLING-4554

Regards,

Peter

 

Hi Peter,

Unfortunately for my team, despite upgrading to AEM 6.2, we don't have scope to rework all JSP/JSTL components into HTL components. To the best of my knowledge, and limited local testing, I can't utilize WCMUsePojo/HTL in a JSP component, which unfortunately means that the method you're suggesting wouldn't work here.

Is it worth (any potential resource hit?) making my standard util class a @Service just so I can @Reference the ResourceResolverFactory? Or would you recommend I simply do what I mentioned in my reply above, getting the ServiceReference from the BundleContext, etc.?

Avatar

Level 5

smacdonald2008 wrote...

I would go the @Service approach. 

 

Any idea if there is any sort of performance degradation* from doing this simply to provide the @Reference capability to a class/interface? Couldn't tell just from looking at the documentation[1].

* other than a couple extra <service> declaration lines in the META-INF file.

[1] http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin/scr-annotations.html...

Avatar

Correct answer by
Community Advisor

Would not assume so, @Service is just an annotation, behind the scenes SCR xml get's saved into OSGi/SCR service resolution mappings system which is fairly transparent and fast. Calling Service method itself is lighting fast(write simple Apache Felix test to see this yourself). What gives it time is the logic that you put in body of the method call.

Regards,

Peter

Avatar

Level 5

Thanks for both replies, Peter, very helpful!

Quick question, did you intentionally delete the one about the OSGi book?

Avatar

Community Advisor

Yes, confirm.

Regards,

Peter