Call OSGi service from sightly javascript use function - aem

I am trying to access an OSGi service from a sightly javascript use function. Through the sling SlingScriptHelper. I can call the sling.getService(Service.class) method from javascript, but I do not know how to specify the class in javascript.
It looks like it should be possible to reference java classes using the fully qualified name or using rhino's importPackage(..).
However, I get the following exception:
org.apache.sling.scripting.sightly.SightlyException:
org.mozilla.javascript.EvaluatorException: Can't find method
org.apache.sling.scripting.core.impl.InternalScriptHelper.getService(object).

To do this, prepend Packages to the fully-qualified class name, e.g.
var myService = sling.getService(Packages.com.myco.MyService);
(where com.myco.MyService is the service interface)
See https://github.com/Adobe-Consulting-Services/acs-aem-commons/blob/master/content/src/main/content/jcr_root/apps/acs-commons/sightly/templates/dhlm.js#L23 for an example.

Related

Multiple selectors using Sling Servlets

Short version: How do I force the most matching on a servlet based on multiple selectors using Felix annotations for sling servlets?
I have a few servlets defined in an OSGI bundle. I'm using the org.apache.felix.scr.annotations.sling.SlingServlet annotations.
#SlingServlet(
methods={GET},
selectors {"v1"}
...
)
public class MyServlet extends SlingAllMethodsServlet {}
...
#SlingServlet(
methods={GET},
selectors {"v1","special"}
...
)
public class MySpecialServlet extends MyServlet {}
My problem is that I can not find a way to force MySpecialServlet to only handle requests when both selectors are present.
GET http://localhost/my/resource.v1.special.json
Sometimes it will handle requests for only the v1 selector.
GET http://localhost/my/resource.v1.json
It seems that after using posting a new jar through the felix webconsole, if I request the double selector resource.v1.special.json before any other resource, then MySpecialServlet will also continue to handle v1 only requests.
Is there a way I can force the more general servlet to handle the more general list of selectors using the current annotations? Am I missing some part annotation? I believe that this system might be using an older annotation. Perhaps it is worth migrating? I'm trying not to be too intrusive for this small task that I've been asked to do.
Bear with me if I've conflated parts of these technologies. I've just walked up to this problem and I'm still sorting it out. Please correct any misalignment of terms.
Register your MySpecialServlet by v1.special, like selectors = {"v1.special"}.
According to the documentation:
... The selectors must be configured as they would be specified in the URL that is as a list of dot-separated strings such as print.a4 ...
I understand that when registering the servlet by a list of selectors, Sling treats them individually (as within OR condition). So, in the case of registering your special servlet by selectors = {"v1","special"}, the doGet method will be called if you request:
http://localhost/my/resource.v1.special.json or
http://localhost/my/resource.special.json or
http://localhost/my/resource.v1.json

spring rest data plural url

I have a domain class called StoreType.java which is exposed by below spring repository
public interface StoreTypeRepository extends PagingAndSortingRepository<StoreType, Short> {
}
When I access this using url http://localhost:8080/my-persistence/jpa/storetypes it returns 404.
if I change my domain class as Storetype (without camel case), it works fine and return 200 OK.
I have few more repositories which uses single world domain classes like Store.java , Country.java and these work fine and by default these exposed as plural of domain class name.
I know spring exposed url as plural of domain classes but not sure why it is not exposing it. I can override this using #RepositoryRestResource(path="/storetypes") but I want to know what is default rest url if domain classes name in camel case.
You seem to have answered the question to your problem by specifying the #RepositoryRestResource( path="/storetypes" ) annotation as the documentation states.
Spring Data REST exposes a collection resource named after the uncapitalized, pluralized version of the domain class the exported repository is handling. Both the name of the resource and the path can be customized using the #RepositoryRestResource on the repository interface.
In this case your naming convention seems correct using StoreTypeRepository however one thing confuses me about your repository definition... I'm not sure why you set the type parameter to the PagingAndSortingRepository<StoreType, Short> but I'm quite certain that's incorrect as the second type parameter should be of type Long.

JAXRS tries to call Interface instead of Implementation

I got a JAXRS application. I have an Interface class (SomeResource) (where i put most of my annotations) and an implementation of this interface (SomeService).
I have registered the SomeService.class in the overriden JaxRSApplication method .getClasses();
All my other services/resources are implemented in the same way, but whenever i try to call this one service (SomeService), i get the following exception:
"Error 500: javax.servlet.ServletException: java.lang.IllegalAccessException: Class org.apache.wink.server.internal.handlers.InvokeMethodHandler can not access a member of class package.api.SomeResource with modifiers "public abstract""
As you can see, for some reason, this one Service tries to call the Resource(Interface) instead of the the Service class with the actual implementation.
Anyone got an idea how to resolve this? (Real classnames hidden because of security).
Be sure to declare the implementation class of the service (SomeService.class) with its full qualified classname and not the interface within your rest service configurationen of your application.
The way you have to do that depends on the implementing framework.
Have a look here:
http://cxf.apache.org/docs/jaxrs-services-configuration.html

Using the Apache felix SCR Annoration #Reference in Scala, for an OSGI environment

I am trying to use the #Reference Felix SCR annotation in Scala
This is how it can be used in Java:
public class Foo {
#Reference
MyServiceInterface service;
// some code here
}
Here, MyService is ideally a Java Interface and not a concrete class (dependency injection)
I am using the same annotation in Scala, trying to depend on the same MyService (a Java Interface), like:
class Foo {
#Reference
val service = MyServiceInterface // ??
// some code here
}
How can I use this annotation in Scala, to refer to a Java Interface?
example:
#Reference
val MyServiceInterface service
or
#Reference
val service = MyServiceInterface
is not valid Scala code
Thank you
I know very little about Scala but I believe "val" means an immutable value, and thus it makes very little sense to bind it to a (mutable) service reference.
Shouldn't this member field be declared with "def" or "var" instead? In which case maybe the annotation will be allowed.
The reference annotation has a interfaceReference attribute.
This attribute can be used to specify the java interface.
I assume in scala it would look like (never used Felix Annotation in scala):
#Reference(interfaceReference = MyServiceInterface)
val MyServiceInterface service
It might be that you also have to specify the bind and unbind method in this case.
Please see also Felix Annotations documentation
Since 1.9.0 Felix Annotation are runtime annotations. The Annotation Felix Processor has an option scanClasses to use classes instead of source code to process the annotations. This works perfectly fine with groovy. I see no reason why that should not work with Scala.
If you use Intellij then please have a look at the Felix Annotation Plugin. The plugin uses by default scan classes
I was able to solve this problem by specifying the type of the variable correctly like:
#Reference
var service: MyServiceInterface = null
#Neil is right, we must use a var instead of a val as the service binding happens at runtime.
Secondly, I had to add the following configuration to the maven-scr-plugin:
<configuration>
<scanClasses>true</scanClasses>
</configuration>
Then, I had to specifically instruct the Maven Bundle plugin to NOT import the org.apache.felix.scr.annotations package as follows:
<Import-Package>!org.apache.felix.scr.annotations, *</Import-Package>
because the manifest would otherwise include an entry for this package as something that the bundle depends on.
Once this was done, the mvn-scr-plugin would generate the XML file correctly and the mvn-bundle-plugin would generate the bundle, manifest correctly.

generate JSNI on-fly

I have some java object and I want to expose all methods of it to custom javascript object. So, seems it would be reasonable to loop over all java object members, via reflection, and generate jsni code like: $wnd.myjso.func1 = function() { #package.MyJavaObject::func1()} and so on... Afterwards generated jsni must be executed to create javascript object on browser's window. How to implement it?
As you cannot use reflection at run-time, you have to do it at compile-time, using a GWT Generator.
That being said, you don't need to write such a generator by yourself, someone (now a Googler, member of the GWT team) has already done so: http://code.google.com/p/gwt-exporter/