Re: How to create Rest APIs for non-JCR data in Sling 8??

2017-01-28 Thread Ben Fortuna
Hi Henry,

I agree with what you say about keeping it simple and using a servlet.
However there are many frameworks and platforms today geared towards making
it easier to implement REST APIs, and I think non-trivial APIs would
probably benefit from using one.

As such, to me an API should live outside the Sling process and use sling
as a data/content source.

Regards,
Ben

On 29 Jan 2017 6:09 AM, "Henry Saginor"  wrote:

> In my opinion Sling is first and foremost a REST framework specifically
> designed for this kind of thing. It’s not only to serve JCR content.
> The paradigm Steven described earlier in this thread is EXACTLY the way to
> implement it. In the Sling world the resource IS the RESTful object
> addressable via a URI. The only thing I can add, as I wrote before, is that
> it’s not necessary to implement a custom resource provider.
> You can simply create JCR nodes/resources to map to your resource type via
> sling:resourceType. And what your servlet returns is up to you and your
> requirements. That works in most cases.
> You can easily integrate your servlet with existing OSGi service via
> declarative services and use any framework/library you need internally
> (provided you can make it available in OSGi container) to integrate with
> your data where it adds value.
> But in my opinion it does not make sense integrating Sling with other
> framework, such as Spring, which follow different paradigms to do the same
> things as Sling + Declarative Services. It increases complexity and does
> not add value.
>
> My advice is don’t shoot yourself in the foot and keep things as simple as
> possible. Just implement a servlet, integrate with existing service via DS
> if needed, and format and return the response based on your requirements.
> Then create a resource (JCR or custom ResourceProvider), map it to your
> servlet via sling:resourceType. This is how I have always implemented
> RESTful services in Sling without many limitations. The framework is
> specifically designed for this.
>
> Henry
>
> > On Jan 28, 2017, at 7:57 AM, Jason E Bailey 
> wrote:
> >
> >
> > Its my understanding that the question on ACL's depends on where it is
> > inheriting the ACL from. Taking your code as literal, you've declared
> > that you own everything under /things and it would inherit the ACL of /.
> > So if you put your ROOT as /content/remote/things You could set JCR ACLs
> > on /content/remote.
> >
> > Theoretically I assume that your resource could provide an ACL as the
> > ACL is just a resource in the tree.
> I am not sure if you can do this since ACLs are at JCR level and are
> checked via JCR.
> >
> > As others suggested using a resource provider in this way may not be the
> > best solution. As the whole point of Sling is to manage content and
> > splitting it into different pieces can be awkward.
> >
> > I'm assuming that you don't need to do POST operations, and that using
> > Oak with an S3 file storage configuration is out.
> >
> > If you can tell Sling what's on the remote store, you could just use a
> > reference to the data. In the same way that in AEM, an image component
> > doesn't necessarily have the image, rather it can have a pointer to the
> > image.  So your renderer can just go out and retrieve the image and
> > return it.
> >
> > Or, the Sling Resource Merger
> > https://sling.apache.org/documentation/bundles/resource-merger.html
> >
> > In this case you can merge your resource provider with a JCR Path. So
> > that your resource provider provides the remote content while the
> > associated meta data can be stored in the JCR. Haven't tried this myself
> > though.
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > --
> > Jason
> >
> > On Fri, Jan 27, 2017, at 04:27 PM, lancedolan wrote:
> >> Hi friends,
> >>
> >> I've tried routing questions through stackoverflow to cut down my mails
> >> to
> >> this list. I'm losing lots of time on this one, though, and am stuck.
> >>
> >> I need to create APIs which don't represent Sling Resources. Example:
> >> /services/images/123123123
> >> that image will exist somewhere else.
> >>
> >> Bertrand suggests creating a ResourceProvider, as in the example here
> >> [1].
> >> However, that uses the spi package which is not in version 2.9.0 of
> >> org.apache.sling.api, and thus, not available to me in Sling 8.
> >>
> >> I did find a ResourceProvider interface to implement though, and created
> >> this code:
> >>
> >> /**
> >> * Created by lancedolan on 1/27/17.
> >> */
> >> @Component
> >> @Service(value=ResourceProvider.class)
> >> @Properties({
> >>@Property(name = ResourceProvider.ROOTS, value = "things"),
> >>@Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
> >> })
> >> public class ImageResourceProvider implements ResourceProvider {
> >>
> >>/** If this provider required a context this would be more elaborate,
> >> *  but for this simple example we don't need one.
> >> */
> 

Re: How to create Rest APIs for non-JCR data in Sling 8??

2017-01-28 Thread Henry Saginor
In my opinion Sling is first and foremost a REST framework specifically 
designed for this kind of thing. It’s not only to serve JCR content.
The paradigm Steven described earlier in this thread is EXACTLY the way to 
implement it. In the Sling world the resource IS the RESTful object addressable 
via a URI. The only thing I can add, as I wrote before, is that it’s not 
necessary to implement a custom resource provider.
You can simply create JCR nodes/resources to map to your resource type via 
sling:resourceType. And what your servlet returns is up to you and your 
requirements. That works in most cases. 
You can easily integrate your servlet with existing OSGi service via 
declarative services and use any framework/library you need internally 
(provided you can make it available in OSGi container) to integrate with your 
data where it adds value.
But in my opinion it does not make sense integrating Sling with other 
framework, such as Spring, which follow different paradigms to do the same 
things as Sling + Declarative Services. It increases complexity and does not 
add value.

My advice is don’t shoot yourself in the foot and keep things as simple as 
possible. Just implement a servlet, integrate with existing service via DS if 
needed, and format and return the response based on your requirements. Then 
create a resource (JCR or custom ResourceProvider), map it to your servlet via 
sling:resourceType. This is how I have always implemented RESTful services in 
Sling without many limitations. The framework is specifically designed for this.

Henry  
 
> On Jan 28, 2017, at 7:57 AM, Jason E Bailey  wrote:
> 
> 
> Its my understanding that the question on ACL's depends on where it is
> inheriting the ACL from. Taking your code as literal, you've declared
> that you own everything under /things and it would inherit the ACL of /.
> So if you put your ROOT as /content/remote/things You could set JCR ACLs
> on /content/remote.
> 
> Theoretically I assume that your resource could provide an ACL as the
> ACL is just a resource in the tree.
I am not sure if you can do this since ACLs are at JCR level and are checked 
via JCR. 
> 
> As others suggested using a resource provider in this way may not be the
> best solution. As the whole point of Sling is to manage content and
> splitting it into different pieces can be awkward.
> 
> I'm assuming that you don't need to do POST operations, and that using
> Oak with an S3 file storage configuration is out.
> 
> If you can tell Sling what's on the remote store, you could just use a
> reference to the data. In the same way that in AEM, an image component
> doesn't necessarily have the image, rather it can have a pointer to the
> image.  So your renderer can just go out and retrieve the image and
> return it.
> 
> Or, the Sling Resource Merger
> https://sling.apache.org/documentation/bundles/resource-merger.html
> 
> In this case you can merge your resource provider with a JCR Path. So
> that your resource provider provides the remote content while the
> associated meta data can be stored in the JCR. Haven't tried this myself
> though.
> 
> 
> 
> 
> 
> 
> 
> 
> 
> --
> Jason
> 
> On Fri, Jan 27, 2017, at 04:27 PM, lancedolan wrote:
>> Hi friends,
>> 
>> I've tried routing questions through stackoverflow to cut down my mails
>> to
>> this list. I'm losing lots of time on this one, though, and am stuck.
>> 
>> I need to create APIs which don't represent Sling Resources. Example:
>> /services/images/123123123
>> that image will exist somewhere else.
>> 
>> Bertrand suggests creating a ResourceProvider, as in the example here
>> [1].
>> However, that uses the spi package which is not in version 2.9.0 of
>> org.apache.sling.api, and thus, not available to me in Sling 8.
>> 
>> I did find a ResourceProvider interface to implement though, and created
>> this code:
>> 
>> /**
>> * Created by lancedolan on 1/27/17.
>> */
>> @Component
>> @Service(value=ResourceProvider.class)
>> @Properties({
>>@Property(name = ResourceProvider.ROOTS, value = "things"),
>>@Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
>> })
>> public class ImageResourceProvider implements ResourceProvider {
>> 
>>/** If this provider required a context this would be more elaborate,
>> *  but for this simple example we don't need one.
>> */
>>public static class DoesNotNeedAContext {
>>};
>> 
>>@Override
>>public Resource getResource(ResourceResolver resourceResolver, String
>> path) {
>>Resource returnResource = new SyntheticResource(resourceResolver,
>> path, "edlio/microservice/image");
>>returnResource.getValueMap().put("myProp" , "myValue");
>>return returnResource;
>>}
>> 
>>@Override
>>public Resource getResource(ResourceResolver resourceResolver,
>> HttpServletRequest httpServletRequest, String path) {
>>return getResource(resourceResolver , path);
>>}
>> 
>>@Override

Re: How to create Rest APIs for non-JCR data in Sling 8??

2017-01-28 Thread Jason E Bailey

Its my understanding that the question on ACL's depends on where it is
inheriting the ACL from. Taking your code as literal, you've declared
that you own everything under /things and it would inherit the ACL of /.
So if you put your ROOT as /content/remote/things You could set JCR ACLs
on /content/remote.

Theoretically I assume that your resource could provide an ACL as the
ACL is just a resource in the tree.

As others suggested using a resource provider in this way may not be the
best solution. As the whole point of Sling is to manage content and
splitting it into different pieces can be awkward.

I'm assuming that you don't need to do POST operations, and that using
Oak with an S3 file storage configuration is out.

If you can tell Sling what's on the remote store, you could just use a
reference to the data. In the same way that in AEM, an image component
doesn't necessarily have the image, rather it can have a pointer to the
image.  So your renderer can just go out and retrieve the image and
return it.

Or, the Sling Resource Merger
https://sling.apache.org/documentation/bundles/resource-merger.html

In this case you can merge your resource provider with a JCR Path. So
that your resource provider provides the remote content while the
associated meta data can be stored in the JCR. Haven't tried this myself
though.









--
Jason

On Fri, Jan 27, 2017, at 04:27 PM, lancedolan wrote:
> Hi friends,
> 
> I've tried routing questions through stackoverflow to cut down my mails
> to
> this list. I'm losing lots of time on this one, though, and am stuck.
> 
> I need to create APIs which don't represent Sling Resources. Example:
> /services/images/123123123
> that image will exist somewhere else.
> 
> Bertrand suggests creating a ResourceProvider, as in the example here
> [1].
> However, that uses the spi package which is not in version 2.9.0 of
> org.apache.sling.api, and thus, not available to me in Sling 8.
> 
> I did find a ResourceProvider interface to implement though, and created
> this code:
> 
> /**
>  * Created by lancedolan on 1/27/17.
>  */
> @Component
> @Service(value=ResourceProvider.class)
> @Properties({
> @Property(name = ResourceProvider.ROOTS, value = "things"),
> @Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
> })
> public class ImageResourceProvider implements ResourceProvider {
> 
> /** If this provider required a context this would be more elaborate,
>  *  but for this simple example we don't need one.
>  */
> public static class DoesNotNeedAContext {
> };
> 
> @Override
> public Resource getResource(ResourceResolver resourceResolver, String
> path) {
> Resource returnResource = new SyntheticResource(resourceResolver,
> path, "edlio/microservice/image");
> returnResource.getValueMap().put("myProp" , "myValue");
> return returnResource;
> }
> 
> @Override
> public Resource getResource(ResourceResolver resourceResolver,
> HttpServletRequest httpServletRequest, String path) {
> return getResource(resourceResolver , path);
> }
> 
> @Override
> public Iterator listChildren(Resource resource) {
> return null;
> }
> }
> 
> 
> The result is that I get a 403 response. How do I control the
> authentication
> for resources that don't actually exist? The fact that I'm not getting
> 404
> means that my ResourceProvider is at least registering successfully. 
> 
> Finally, I'd much prefer to use Jersey if possible... Anybody have
> success
> getting Jersey to work in Sling 8? I dumped a bunch of time into it and
> gave
> up after class not found errors for classes that should be found [2].
> 
> The ultimate goal is just to provide a restful API in Sling 8 and the
> static-path-declaration of SlingSafeMethodsServlet just doesn't cut it.
> 
> Thanks a million guys...
> 


Re: How to create Rest APIs for non-JCR data in Sling 8??

2017-01-28 Thread Roy Teeuwen
Hey Oli,

Isnt that the whiteboard that I gave?
https://github.com/apache/aries-jax-rs-whiteboard 


Greets
Roy


> On 28 Jan 2017, at 09:43, olimination  wrote:
> 
> Hi Lance,
> 
> as Mike already mentioned the "Neba framework" offers you the full
> Spring power, meaning you can easily write Spring controllers which then
> for example inject your needed OSGi services and you then do whatever
> you need to do plus you have access to all the possibilities Spring
> offers you.
> 
> See doc here: http://neba.io/documentation.html#spring_mvc
> 
> Or as far as I know with OSGi R7 there will be support for JAX-RS.
> 
> See here: https://adapt.to/2016/en/schedule/osgi-r7.html
> 
> cheers,
> Oli
> 
> On 28.01.2017 07:23, Henry Saginor wrote:
>> Can’t you just create sling servlet registered to some resource type? 
>> You can then simply create JCR node(s) mapped to your resource type. 
>> You can also use a SynthaticResource via custom resource provider, which is 
>> the track you’re on and what Steven is suggesting. 
>> But I find that in most cases just creating a JCR node is more convenient 
>> and you can apply JCR ACLs to it control access if you need it. 
>> 
>>> On Jan 27, 2017, at 9:34 PM, Steven Walters  wrote:
>>> 
>>> On Sat, Jan 28, 2017 at 6:27 AM, lancedolan  wrote:
 Hi friends,
 
 I've tried routing questions through stackoverflow to cut down my mails to
 this list. I'm losing lots of time on this one, though, and am stuck.
 
 I need to create APIs which don't represent Sling Resources. Example:
 /services/images/123123123
 that image will exist somewhere else.
 
 Bertrand suggests creating a ResourceProvider, as in the example here [1].
 However, that uses the spi package which is not in version 2.9.0 of
 org.apache.sling.api, and thus, not available to me in Sling 8.
 
 I did find a ResourceProvider interface to implement though, and created
 this code:
 
 /**
 * Created by lancedolan on 1/27/17.
 */
 @Component
 @Service(value=ResourceProvider.class)
 @Properties({
   @Property(name = ResourceProvider.ROOTS, value = "things"),
   @Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
 })
 public class ImageResourceProvider implements ResourceProvider {
 
   /** If this provider required a context this would be more elaborate,
*  but for this simple example we don't need one.
*/
   public static class DoesNotNeedAContext {
   };
 
   @Override
   public Resource getResource(ResourceResolver resourceResolver, String
 path) {
   Resource returnResource = new SyntheticResource(resourceResolver,
 path, "edlio/microservice/image");
   returnResource.getValueMap().put("myProp" , "myValue");
   return returnResource;
   }
 
   @Override
   public Resource getResource(ResourceResolver resourceResolver,
 HttpServletRequest httpServletRequest, String path) {
   return getResource(resourceResolver , path);
   }
 
   @Override
   public Iterator listChildren(Resource resource) {
   return null;
   }
 }
 
 
 The result is that I get a 403 response. How do I control the 
 authentication
 for resources that don't actually exist? The fact that I'm not getting 404
 means that my ResourceProvider is at least registering successfully.
 
 Finally, I'd much prefer to use Jersey if possible... Anybody have success
 getting Jersey to work in Sling 8? I dumped a bunch of time into it and 
 gave
 up after class not found errors for classes that should be found [2].
 
 The ultimate goal is just to provide a restful API in Sling 8 and the
 static-path-declaration of SlingSafeMethodsServlet just doesn't cut it.
 
 Thanks a million guys...
>>> 
>>> The Sling paradigm for this is to create resources through the
>>> resource provider,
>>> and then create/register a servlet to respond to the resource type
>>> you're creating (not a static path).
>>> 
>>> So from your above code, you'd create an additional servlet registered
>>> to the resourceType "edlio/microservice/image" (instead of registered
>>> to a static path) and implement GET inside it.
>>> 
>>> Without the corresponding servlet, this is most likely being served by
>>> the default GET servlet, which will not particularly understand how to
>>> deal with these resources, thus the errors.
>> 
>> 



Re: How to create Rest APIs for non-JCR data in Sling 8??

2017-01-28 Thread olimination
Hi Lance,

as Mike already mentioned the "Neba framework" offers you the full
Spring power, meaning you can easily write Spring controllers which then
for example inject your needed OSGi services and you then do whatever
you need to do plus you have access to all the possibilities Spring
offers you.

See doc here: http://neba.io/documentation.html#spring_mvc

Or as far as I know with OSGi R7 there will be support for JAX-RS.

See here: https://adapt.to/2016/en/schedule/osgi-r7.html

cheers,
Oli

On 28.01.2017 07:23, Henry Saginor wrote:
> Can’t you just create sling servlet registered to some resource type? 
> You can then simply create JCR node(s) mapped to your resource type. 
> You can also use a SynthaticResource via custom resource provider, which is 
> the track you’re on and what Steven is suggesting. 
> But I find that in most cases just creating a JCR node is more convenient and 
> you can apply JCR ACLs to it control access if you need it. 
> 
>> On Jan 27, 2017, at 9:34 PM, Steven Walters  wrote:
>>
>> On Sat, Jan 28, 2017 at 6:27 AM, lancedolan  wrote:
>>> Hi friends,
>>>
>>> I've tried routing questions through stackoverflow to cut down my mails to
>>> this list. I'm losing lots of time on this one, though, and am stuck.
>>>
>>> I need to create APIs which don't represent Sling Resources. Example:
>>> /services/images/123123123
>>> that image will exist somewhere else.
>>>
>>> Bertrand suggests creating a ResourceProvider, as in the example here [1].
>>> However, that uses the spi package which is not in version 2.9.0 of
>>> org.apache.sling.api, and thus, not available to me in Sling 8.
>>>
>>> I did find a ResourceProvider interface to implement though, and created
>>> this code:
>>>
>>> /**
>>> * Created by lancedolan on 1/27/17.
>>> */
>>> @Component
>>> @Service(value=ResourceProvider.class)
>>> @Properties({
>>>@Property(name = ResourceProvider.ROOTS, value = "things"),
>>>@Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
>>> })
>>> public class ImageResourceProvider implements ResourceProvider {
>>>
>>>/** If this provider required a context this would be more elaborate,
>>> *  but for this simple example we don't need one.
>>> */
>>>public static class DoesNotNeedAContext {
>>>};
>>>
>>>@Override
>>>public Resource getResource(ResourceResolver resourceResolver, String
>>> path) {
>>>Resource returnResource = new SyntheticResource(resourceResolver,
>>> path, "edlio/microservice/image");
>>>returnResource.getValueMap().put("myProp" , "myValue");
>>>return returnResource;
>>>}
>>>
>>>@Override
>>>public Resource getResource(ResourceResolver resourceResolver,
>>> HttpServletRequest httpServletRequest, String path) {
>>>return getResource(resourceResolver , path);
>>>}
>>>
>>>@Override
>>>public Iterator listChildren(Resource resource) {
>>>return null;
>>>}
>>> }
>>>
>>>
>>> The result is that I get a 403 response. How do I control the authentication
>>> for resources that don't actually exist? The fact that I'm not getting 404
>>> means that my ResourceProvider is at least registering successfully.
>>>
>>> Finally, I'd much prefer to use Jersey if possible... Anybody have success
>>> getting Jersey to work in Sling 8? I dumped a bunch of time into it and gave
>>> up after class not found errors for classes that should be found [2].
>>>
>>> The ultimate goal is just to provide a restful API in Sling 8 and the
>>> static-path-declaration of SlingSafeMethodsServlet just doesn't cut it.
>>>
>>> Thanks a million guys...
>>
>> The Sling paradigm for this is to create resources through the
>> resource provider,
>> and then create/register a servlet to respond to the resource type
>> you're creating (not a static path).
>>
>> So from your above code, you'd create an additional servlet registered
>> to the resourceType "edlio/microservice/image" (instead of registered
>> to a static path) and implement GET inside it.
>>
>> Without the corresponding servlet, this is most likely being served by
>> the default GET servlet, which will not particularly understand how to
>> deal with these resources, thus the errors.
> 
>