click-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bob Schellink <sab...@gmail.com>
Subject Re: Click Services
Date Mon, 20 May 2013 13:08:22 GMT
I was thinking ClickServlet should be revamped into a filter to support
Services, but perhaps a separate Filter is more appropriate. Also as Naoki
mentioned, Click is predominantly a Page framework, so the Service stuff
could be placed into a separate jar?

Kind regards

Bob

On Mon, May 20, 2013 at 3:04 PM, Bob Schellink <sabob1@gmail.com> wrote:

> I don't personally use stateful services so we could start without
> supporting them. We have also deprecated stateful Pages.
>
> Makes sense not to have any type of life cycle methods then too.
>
> The properties idea is interesting. One advantage is i18n. On the other
> hand it moves the doco away from the code, which makes it more difficult
> and unlikely to be updated.
>
> On that note, is it even possible to invoke a service method and pass in
> arguments eg:
>
> CustomerService.getCustomers(String arg1, String arg2)
>
> How would we be able to know which request parameter to pass to arg1? If
> the argument name ("arg1" in this case)  is not available via reflection it
> might not be possible to figure out which arg goes where.
>
> I know JAX RS uses annotations to specify args eg:
> CustomerService.getCustomers(@QueryParam("arg1") String arg1,
> @QueryParam("arg2") String arg2)
>
> If we use annotations for args then we can also use those annotations for
> docs.
>
> So there are a couple of ways for Click to support invoking a service
> method:
> 1) Use no-arg methods and pull the request parameters through the Servlet
> API. Won't be able to auto document this option
> 2) Pass in primitive arguments (Strings, integer etc.)
> 3) Pass in a DTO (for posting JSON)
>
> Not sure if we should support some or all of them. Should be fairly easy
> though as we've solved most of these problems already with Click.
>
> Kind regards
>
> Bob
>
>
> On Mon, May 20, 2013 at 2:09 PM, Malcolm Edgar <malcolm.edgar@gmail.com>wrote:
>
>> Another approach for generating documentation would be to use a class
>> properties file and look up the HTML doco based on the method name, e.g.
>>
>> CustomerServivce.properties
>> ---------------------------------------------------------------------
>>
>> CustomerServivce = Providers Customer Account query services.
>>
>> getCustomers = Return the list of customers matching the given keyword
>> and active status. \n\
>>  param : keyword : String : Search for customers matching the keyword
>> (optiona) \n\
>>         param : active : boolean : Include only active accounts
>> (optional)" \n\
>>         return : customer : array of customers
>>
>>
>> regards Malcolm
>>
>>
>> On Mon, May 20, 2013 at 9:07 PM, Malcolm Edgar <malcolm.edgar@gmail.com>wrote:
>>
>>> Hi Bob,
>>>
>>> thanks for the links to Roy's blog post. I have to admit I have used the
>>> REST terminology a lot when talking about JSON RPC, so I am trying to be
>>> more precise nowdays.
>>>
>>> The WADL looks interesting, however writing an XML descriptor to
>>> generate doco would not be fun.
>>>
>>> Using straight reflection wouldn't probably work because the Java
>>> reflection API doesn't tell you what the parameter names are.  We would
>>> need to add annotations to make this work.  However writing code with
>>> annotations for doco is pretty yucky, e.g.
>>>
>>> package com.mycorp.services;
>>>
>>> @Doc(desc="Providers Customer Account query services")
>>> public class CustomerService {
>>>
>>>  @Doc(desc="Return the list of customers matching the given keyword and
>>> active status")
>>> public List<Customer> getCustomers(
>>>  @Doc(param="keyword", desc="Search for customers matching the keyword
>>> (optional") String keyword,
>>> @Doc(param="active", desc="Include only active accounts (optional)")
>>> boolean active) {
>>>  ..
>>> }
>>> }
>>>
>>> Still it would be a pretty nice feature to have APIs which are self
>>> describing.
>>>
>>> Its interesting using the returned POJO to create the documentation.
>>> Maybe a valid approach, especially if we can rely on a decent library to do
>>> the marshalling.  Using a reflection based approach would give us the most
>>> flexibility, so you could return an ActionResult or a POJO and the Filter
>>> would handle this result.
>>>
>>> Do you think there is merit in having stateful/singleton services ?
>>>
>>> In terms of mapping, I think we could develop some reasonable
>>> conventions like we have done with Click pages and cache the results, e.g.
>>>
>>> GET
>>> /mycorp/services/customer-service/get-customers/?keyword=john&active=true
>>>
>>> Would attempt to look up the class paths:
>>>
>>> com.mycorp.services.CustomerService
>>>
>>> Then attempt to resolve the method:
>>>
>>> getCustomers(String, String)
>>>
>>> While this is is favoring convention over configuration, in my
>>> experience this works really well in building large systems.
>>>
>>> Would be good for the Filter to use the Click Logging service, and log
>>> the appropriate output depending upon the application mode.
>>>
>>> It would also would be nice to have the Filter support formatting the
>>> JSON response to make it more human readable, with an optional
>>> formatJson=true request parameter.
>>>
>>> While all these things may appear to be pretty minor benefits, I think
>>> they would have a cumulative productivity benefit which would be
>>> significant.
>>>
>>> regards Malcolm
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Mon, May 20, 2013 at 7:14 PM, Bob Schellink <sabob1@gmail.com> wrote:
>>>
>>>> Hi Malcolm,
>>>>
>>>> Multiple requests per service is what I have in mind. JSON over HTTP
>>>> instead of REST.
>>>>
>>>> Interestingly, Roy Fielding says a service isn't REST if it isn't
>>>> hypertext driven:
>>>> http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
>>>>
>>>> Basically nobody is doing REST anyway ;-)
>>>>
>>>> Wrt self documenting efforts, there is Swagger and WADL:
>>>> developers.helloreverb.com/swagger/
>>>>
>>>> Swager Demo:
>>>> http://petstore.swagger.wordnik.com/
>>>>
>>>> WADL:
>>>> http://en.wikipedia.org/wiki/Web_Application_Description_Language
>>>>
>>>> I'm not sure how we could self describe these services though. Perhaps
>>>> a url like '/services' could generate an HTML page with links to all
>>>> registered services. But Click will then have to "discover" it's own
>>>> services somehow via reflection or annotations or at build time.
>>>>
>>>> We also have to provide the input and outputs (JSON) of the services.
>>>> If a service looked like this:
>>>>
>>>> public Person getPerson(String id) {
>>>> }
>>>>
>>>> we could generate the JSON of a Person instance, as long as it has a
>>>> no-args constructor. The JSON won't have any values though so it would look
>>>> like:
>>>>
>>>> {Person: {'firstname': null, 'surname': null, 'dateOfBirth': null}}
>>>>
>>>> unless we add default values for primitives:
>>>> {Person: {'firstname': "example", 'surname': "example", 'dateOfBirth':
>>>> "2013/01/01" }}
>>>>
>>>> If we target JDK7 we could use the new InvokeDynamic instead of
>>>> reflection. InvokeDynamic should be quite a bit faster.
>>>>
>>>> Another note from your example:
>>>> customerservice/getcustomer/?id=123456
>>>>
>>>> how would one dynamically map customerservice to CustomerService? The
>>>> URL would have to respect the class case otherwise we won't be able to look
>>>> it up automatically. Unless there is a mapping somewhere (web.xml or
>>>> annotation) which maps the lower case customerservice to CustomerService.
>>>>
>>>> Kind regards
>>>>
>>>> Bob
>>>>
>>>>
>>>> On Mon, May 20, 2013 at 5:49 AM, Malcolm Edgar <malcolm.edgar@gmail.com
>>>> > wrote:
>>>>
>>>>> I think there is some merit in this stuff for RPC JSON services.
>>>>>
>>>>> I would like to see some form of API documenting feature, this is a
>>>>> problem with existing services they are hard to program to because they
are
>>>>> not self describing like Web Services are. This could be tricky to
>>>>> implement however, and you may want to disable this on production systems.
>>>>>
>>>>> Interesting to think what the design should be:
>>>>>
>>>>> 1) single RPC method per class, with the service implementing some
>>>>> service interface, e.g.
>>>>>
>>>>>    com.mycorp.service.GetCustomerService
>>>>>
>>>>>    /mycorp/service/getcustomer/?id=123456
>>>>>
>>>>>
>>>>> 2) multiple RPC methods per class, using reflection to lookup the
>>>>> methods:
>>>>>
>>>>>    com.mycorp.service.CustomerService
>>>>>
>>>>>    /mycorp/service/customerservice/getcustomer/?id=123456
>>>>>
>>>>>    /mycorp/service/customerservice/getcustomerlist/?keyword=bob
>>>>>
>>>>>
>>>>> In terms of whether we should support singleton /prototype (Spring
>>>>> terminology) services. I distrust stateful services and would prefer
new
>>>>> service instances to be created per request. If people what to cache
stuff,
>>>>> they can do this themselves in the servlet context.  If we take this
>>>>> approach I don't think we need lifecycle methods onInit(), onDestroy()
etc.
>>>>>  This would also keep it simple, we dont need configuration or annoations
>>>>> to describe the service lifecycle.
>>>>>
>>>>> In terms of mapping requests to service, I think Bob's on demand
>>>>> approach would be good where by we cache resolved look-ups. For
>>>>> implementation agree the Filter would be the best approach as this would
>>>>> avoid impacting the ClickServlet and the XML configuration stuff.  It
would
>>>>> be good do have some package automapping stuff like we do with Click
pages.
>>>>> Maybe this could be configure against the filter in the web.xml
>>>>>
>>>>> regards
>>>>>
>>>>>
>>>>> On Wed, May 15, 2013 at 5:43 AM, Bob Schellink <sabob1@gmail.com>wrote:
>>>>>
>>>>>> On 2013/05/14 15:45, Malcolm Edgar wrote:
>>>>>>
>>>>>>> I think this is an interesting discussion.  I am seeing existing
>>>>>>> Multiple Page Applications (MPA),
>>>>>>> which is Clicks forte, evolve into hybrid MPA / Single Page
>>>>>>> Applications (SPA) using frameworks like
>>>>>>> AngularJS.
>>>>>>>
>>>>>>> For serving JSON/RPC we have been using both hand coded Servlets
>>>>>>> with net.sf.json.JSONSerializer and
>>>>>>> using services built with RESTEasy (http://www.jboss.org/resteasy**).
>>>>>>>  The RESTEasy approach is
>>>>>>> more idiomatic Java (lots of layers of abstraction) and works
well
>>>>>>> 99% of time.
>>>>>>>
>>>>>>> I am not sure what the value Click could provide for services.
>>>>>>>
>>>>>>
>>>>>> Nods, we will be reinventing the wheel a bit.
>>>>>>
>>>>>>
>>>>>>  While I agree Velocity templates
>>>>>>
>>>>>>> would be useful for rendering a JSON response, the main problem
in
>>>>>>> this space is marshalling JSON
>>>>>>> request data into Java objects. Maybe Marco google library would
be
>>>>>>> good for this.
>>>>>>>
>>>>>>
>>>>>> I'm currently using GSON[1], mostly because their docs is
>>>>>> straightforward.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> How would you see the services being registered, e.g. XML definition
>>>>>>> or auto-mapped some how ?
>>>>>>>
>>>>>>
>>>>>> Guess annotation based but it looks like a pain to discover the
>>>>>> annotated classes. There are some libs to help with that part but
EE
>>>>>> environments are tricky eg. JBoss 7 has a custom file system implementation
>>>>>> which is tricky to 'scan'. Preprocessor could also be used at compile
time
>>>>>> to discover annotated classes and build an index of classes.
>>>>>>
>>>>>> One could also use plain interfaces and build up a cache at runtime
>>>>>> eg: each request that matches a valid class is placed in a map and
cached
>>>>>> for faster retrieval in the future.
>>>>>>
>>>>>> Kind regards
>>>>>>
>>>>>> Bob
>>>>>>
>>>>>> [1]: http://code.google.com/p/**google-gson/<http://code.google.com/p/google-gson/>
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>

Mime
View raw message