9 Replies Latest reply on Sep 10, 2012 8:52 PM by lancedolan

    How to get SlingScriptHelper in servlet?

    lancedolan Level 1

      I need to get a SlingScriptHelper instance from within my servlet. Either a ComponentContext or BundleContext will do as well, as my only goal is to get sling services using it.

       

      • Using SCR @Reference injection is not a solution for me, because I will determine at runtime what service class I need to get.
      • I've seen posts online that use an activate() method to get ComponentContext, and also decompiled some class that do it, but don't know how to cause sling to call this method and set my ComponentContext
      • I've tried pulling it from the Request scope as an attribute, but sling apparently only puts it there for scripts, not servlets.
      • I've tried injecting all of these objects themselves - none can be injected.

       

      Any help? I'm hoping there's some static factory I can just hit and get one of these objects so that I can get services...

        • 1. Re: How to get SlingScriptHelper in servlet?
          hypnotec Adobe Employee

          you can get it from the sling request object:

           

                  SlingBindings bindings = (SlingBindings) req.getAttribute(SlingBindings.class.getName());

                  SlingScriptHelper scriptHelper = bindings.getSling();

          • 2. Re: How to get SlingScriptHelper in servlet?
            centgraf

            This can be done using static methods provided by OSGi, assuming you can access any class implemented in a bundle.  Here's an example of accessing the SlingSettingsService.  EnvironmentInfo is the class that implements this method, so FrameworkUtil.getBundle(EnvironmentInfo.class) is equivalent to "get the bundle for the current class".

             

                private static Set<String> getRunModes() {

                    BundleContext bundleContext = FrameworkUtil.getBundle(EnvironmentInfo.class).getBundleContext();

                    ServiceReference settingsRef = bundleContext.getServiceReference(SlingSettingsService.class.getName());

                    SlingSettingsService settings = (SlingSettingsService) bundleContext.getService(settingsRef);

                    return settings.getRunModes();

                }

            • 3. Re: How to get SlingScriptHelper in servlet?
              justin_at_adobe Adobe Employee

              While this may be true, getting it from a request attribute is more efficient as it doesn't involve so many lookups.

               

              Also, there's really no reason to use FrameworkUtil in a DS component.

              • 4. Re: How to get SlingScriptHelper in servlet?
                centgraf Level 1

                Agreed on both points.  However:

                 

                1. I don't think the SlingBindings are initialized for servlets in all circumstances.

                2. DS-style injection doesn't work if a servlet is loaded as a script from the JCR, rather than as an OSGi service.  (Some people don't use the full Maven+Eclipse build process, but prefer Servlet syntax over JSP for specific components.)

                 

                We've been calling the method above on every request, and performance differences have been negligible -- very difficult to even measure.  IMHO, it's not a practical concern.

                • 5. Re: How to get SlingScriptHelper in servlet?
                  lancedolan Level 1

                  As Centgraf said, the SlingBindings object is not always put into the request scope for servlets (definitely not in my case). In fact I wrote all of my framework and underlying service layers assuming that I'd be able to do so, and finding out that the SlingBindings isn't on the request attributes is the reason for my spurring this entire thread.

                   

                  To further hammer in my requirement, I have written many sling services which are NOT servlets which also need to do this, so my requirments is definitely to obtain an instance of one of these classes WITHOUT Bindings residing in request scope.

                   

                  Centgraf:

                   

                  I did try FrameworkUtil.getBundle before creating this thread. That method does not exist on the FrameworkUtil object in the version of sling shipped with CQ5.5 (org.osgi.core-1.2.0.jar)

                   

                  I still have no means of getting a service from within a service except by SCR injection, which is a compile-time decision and I need to make the decision about what service I need at runtime.

                  • 6. Re: How to get SlingScriptHelper in servlet?
                    justin_at_adobe Adobe Employee

                    I think there's some confusion here, probably because there are two different types of servlets used in Sling. The first, and far more common, is servlets which are registered as OSGi services. For these, there is no SlingBindings object available because these aren't scripts. They are, however, OSGi services, so by definition you have access to the BundleContext. If you're using DS, it is available via the ComponentContext passed to the component's activate() method. From this BundleContext, you can look up whatever services you want with filters, etc.

                     

                    The second type is when Java is used as a scripting language. In this case, the SlingBindings object is available as a request attribute. You can also have the SlingScriptHelper object injected into these services using @Inject. See https://issues.apache.org/jira/browse/SLING-2237.

                     

                    In neither case should FrameworkUtil be used.

                     

                    If there are cases where Java is used as a scripting language AND SlingBindings isn't available as a request object, please file bugs about those cases with steps to reproduce.

                     

                    It sounds like the biggest confusion is that there's a perception that DS components can only have service references injected into them. This is completely wrong. While injection is preferable, it is by no means required.

                    1 person found this helpful
                    • 7. Re: How to get SlingScriptHelper in servlet?
                      lancedolan Level 1

                      Justin:

                       

                      Thanks for your response. It seems my problem is that I don't know what a DS is (declarative service perhaps) or how to use the Activate() method. What class/interface should I extend/implement in order to have this Activate method called? Is there documentation on this? I'm currently googling all over looking for it.

                       

                      Currently, I have a SlingSafeMethodsServlet. If I give it an activate() method it is never called.

                       

                      I also have a service that is simply annotated as a @Component and @Service, I haven't tried giving that an activate() method, I'll try that now.

                       

                      Thanks again

                      • 8. Re: How to get SlingScriptHelper in servlet?
                        justin_at_adobe Adobe Employee

                        Sorry, DS is Declarative Services. It is an OSGi standard for dependency injection/inversion of control. If you have a class annotated with @Component, you can declare a method named activate() and it will be automatically invoked. The most common signature is:

                        protected void activate(ComponentContext ctx) { // do stuff }

                         

                        But other signature are possible. Section 112.5.8 of the OSGi Compendium version 4.2 for other arguments which can be passed.

                         

                        If you need to name this method something other than activate, you can also annotated an arbitrarily named method with @Activate.

                         

                        All of the above is ALSO true for deactivate.

                         

                        HTH,

                        Justin

                        • 9. Re: How to get SlingScriptHelper in servlet?
                          lancedolan Level 1

                          SOLVED

                           

                          My IDE imported com.day.cq.wcm.ComponentContext rather than org.osgi.service.component.ComponentContext.Thus the activate() method signature didn't match up, and my initial attempt to use active() before starting this thread appeared not to work.

                           

                          Wouldn't have discovered it without your help though, guys! Thanks a million.

                           

                          -Lance