You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@olingo.apache.org by "Thierry Templier (JIRA)" <ji...@apache.org> on 2015/02/20 14:10:11 UTC

[jira] [Comment Edited] (OLINGO-573) Olingo-server-extension with framework like approach for request handling

    [ https://issues.apache.org/jira/browse/OLINGO-573?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14328889#comment-14328889 ] 

Thierry Templier edited comment on OLINGO-573 at 2/20/15 1:09 PM:
------------------------------------------------------------------

Hi Michael and Ramesh,

Here are some comments.

I definitively love such approach. It's clear that we need to use some "plumbing code" and I agree that most of them can be integrated in Olingo itself and not use by the service developer. Having such processor interfaces (the Ramesh's ones below) are really valuable and are in the spirit of a framework approach rather than a library one. I think that we don't need in most cases to work on OData request and response objects of Olingo. This will contribute to reduce the amount of code and the complexity of processors.
 
{code:java}
EntitySet readEntitySet(EdmEntitySet es, UriInfoResource uriInfo)
EntitySet readEntitySet(EdmFunction ef, UriInfoResource uriInfo)
long readCount(EdmEntitySet es, UriInfoResource uriInfo)
{code}

 However I wonder if we could go a bit further than static interfaces. Some frameworks (like Spring MVC / REST) leverages an approach where the method signatures to handle requests aren't static. The service developer is free to choose which parameters he wants to have. Such methods are defined with annotations. I find this approach very valuable, flexible and efficient since it allows to get the hints you need very easy. For example, we can have:

{code:java}
@Controller
public class MyController {
    @RequestMapping(method = RequestMethod.GET)
    public Map<String, Appointment> get() { (...) }
 
    @RequestMapping(value="/{day}", method = RequestMethod.GET)
    public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) { (...) }

    @RequestMapping(method = RequestMethod.POST)
    public String add(@Valid AppointmentForm appointment, BindingResult result) { (...) }
}
{code}

In the context of OData / Olingo, we could have something like that:

{code:java}
    @Processor
    public class MyProcessor {

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY_SET)
        public EntitySet readEntitySet(EdmEntitySet es, UriInfoResource uriInfo) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY_SET)
        public EntitySet readEntitySet(EdmEntitySet es, ODataRequest request) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY)
        public Entity readEntity(EdmEntitySet es, @KeyPredicates List<URIParameter> keys) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.UPDATE_ENTITY)
        public Entity updateEntity(EdmEntitySet es, Entity entity, @KeyPredicates List<URIParameter> keys, HttpMethod method) {
            boolean partial = request.getMethod().equals(HttpMethod.PATCH);
            (...)
        }
    }
{code}

This would be a layer upon the classic approach and / or the Ramesh's one. This brings auto-detecting and configuration (based on annotations) of processors against the OData HTTP handler.

Notice that the field type in the annotation could be easily deduced from the method signature in most cases.
 
Thierry


was (Author: templth):
Hi Michael and Ramesh,

Here are some comments.

I definitively love such approach. It's clear that we need to use some "plumbing code" and I agree that most of them can be integrated in Olingo itself and not use by the service developer. Having such processor interfaces (the Ramesh's ones below) are really valuable and are in the spirit of a framework approach rather than a library one. I think that we don't need in most cases to work on OData request and response objects of Olingo. This will contribute to reduce the amount of code and the complexity of processors.
 
    EntitySet readEntitySet(EdmEntitySet es, UriInfoResource uriInfo)
    EntitySet readEntitySet(EdmFunction ef, UriInfoResource uriInfo)
    long readCount(EdmEntitySet es, UriInfoResource uriInfo)

 However I wonder if we could go a bit further than static interfaces. Some frameworks (like Spring MVC / REST) leverages an approach where the method signatures to handle requests aren't static. The service developer is free to choose which parameters he wants to have. Such methods are defined with annotations. I find this approach very valuable, flexible and efficient since it allows to get the hints you need very easy. For example, we can have:

    @Controller
    public class MyController {
        @RequestMapping(method = RequestMethod.GET)
        public Map<String, Appointment> get() { (...) }
 
        @RequestMapping(value="/{day}", method = RequestMethod.GET)
        public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) { (...) }

        @RequestMapping(method = RequestMethod.POST)
        public String add(@Valid AppointmentForm appointment, BindingResult result) { (...) }
    }

In the context of OData / Olingo, we could have something like that:

    @Processor
    public class MyProcessor {

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY_SET)
        public EntitySet readEntitySet(EdmEntitySet es, UriInfoResource uriInfo) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY_SET)
        public EntitySet readEntitySet(EdmEntitySet es, ODataRequest request) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.READ_ENTITY)
        public Entity readEntity(EdmEntitySet es, @KeyPredicates List<URIParameter> keys) { (...) }

        @ProcessorMethod(type = ProcessorMethodKind.UPDATE_ENTITY)
        public Entity updateEntity(EdmEntitySet es, Entity entity, @KeyPredicates List<URIParameter> keys, HttpMethod method) {
            boolean partial = request.getMethod().equals(HttpMethod.PATCH);
            (...)
        }
    }

This would be a layer upon the classic approach and / or the Ramesh's one. This brings auto-detecting and configuration (based on annotations) of processors against the OData HTTP handler.

Notice that the field type in the annotation could be easily deduced from the method signature in most cases.
 
Thierry

> Olingo-server-extension with framework like approach for request handling
> -------------------------------------------------------------------------
>
>                 Key: OLINGO-573
>                 URL: https://issues.apache.org/jira/browse/OLINGO-573
>             Project: Olingo
>          Issue Type: New Feature
>          Components: odata4-server
>    Affects Versions: (Java) V4 4.0.0-beta-02
>            Reporter: Michael Bolz
>
> Dear Community, 
> Based on some discussions on OLINGO-482, there were several discussions merits of the Processor interface design and how it can be improved for sake of the service developer. Based on those discussions, I have implemented an alternative server side framework as extension. I added this in a separate branch called " olingo-server-extension" , you can also find it at [GitHub|https://github.com/apache/olingo-odata4/tree/olingo-server-extension] 
> - This framework currently does not remove any previous Processor interfaces. As extension, these can be evaluated side by side for comparison, then we can decide on the direction best for Olingo in integrating into one module. 
> - This framework designed specially to make the job of service developer as easy as possible to develop a OData service in the quickest time. 
> - Tries to enforce the odata specification rules, where they need to be, before service implementer receives the request for processing 
> - Moves Context URL processing away from service implementer 
> - Automatically works with registered serializers based on the "Content-Type" defined on the request 
> - Makes the building of response, based on request, such that it reflects the context of the request. Thus eliminates service implementer violating the spec expectations. 
> - Provides $metadata schema parser in server side, using which a service implementer can "define" their metadata of the service, rather than current method using the object form. 
> - Provides a full example based on TripPin service. 
> I encourage you take look at the example service in the test section of this module and see how a sample service can be developed. We are looking for your comments and suggestions to improve upon this framework and your support of the design to carry forward. Please do reply, even that is either a +1 or -1 
> I understand that in this new framework, there single interface called "ServiceHandler" for service implementer to develop along with metadata. *If* multiple Processor interfaces is something we really do need, it is fairly straight forward and *easy* to extend the requests to use multiple interfaces as it is currently designed, so that any existing implementations are not broken. 
> Please take an hour or two looking through this and provide your feedback, and suggestions to improve upon. I sincerely appreciate your time. 
> Thanks. 
> Ramesh.. 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)