On Fri, Jul 19, 2013 at 1:24 PM, Chris Geer <[email protected]> wrote: > In the xml file you need to create the bean, then reference it in the > server element near the top. Other than that...no, that should be all. I > assume you set the Path attribute on the resource. > I did. I'm also messing around with the service injection, which may be the issue. Haven't gotten it to work yet though.
> I thought we were going to do pages/<id>/regions/<id>/regionwidgets/<id> > since it makes no sense to manage a region widget outside a region outside > a page? Possibly. Right now I'm just trying to do a proof of concept with the wrapped json object so I picked something simple with the service and rest models already in place. In general though I don't see any value to dealing with region widgets as a nested resource (pages/:id/regions/:id...) over just dealing with them directly. It's just adding weight to the pages controller, rather than breaking them up and dealing with resource concerns separately. I get what you're saying about regions and regionwidgets only making sense in the context of a page, but you could say the same thing for any 1-many associated resource. Both entities are always uniquely identified, so why not deal with them individually? I see an upside of simpler code, consistent api endpoints, and I see no downside. > > > On Fri, Jul 19, 2013 at 10:16 AM, Erin Noe-Payne > <[email protected]>wrote: > >> I'm trying to register a new endpoint for regionWidgets. I've added >> the interface and default implementation, and created / registered the >> bean in cxf-applicationContext.xml. >> >> However, when I hit the endpoint I get an error: >> [INFO] [talledLocalContainer] WARN : >> org.apache.cxf.jaxrs.utils.JAXRSUtils - No operation matching request >> path "/portal/api/rest/regionWidgets/1" is found, Relative Path: /1, >> HTTP Method: GET, ContentType: */*, Accept: >> text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,. >> Please enable FINE/TRACE log level for more details. >> >> Is there anything else I need to do in order to create and register a >> new endpoint? >> >> On Tue, Jul 16, 2013 at 11:53 PM, Erin Noe-Payne >> <[email protected]> wrote: >> > On Tue, Jul 16, 2013 at 10:24 PM, Chris Geer <[email protected]> >> wrote: >> >> On Tue, Jul 16, 2013 at 7:04 PM, Erin Noe-Payne < >> [email protected]>wrote: >> >> >> >>> On Tue, Jul 16, 2013 at 9:20 PM, Matt Franklin < >> [email protected]> >> >>> wrote: >> >>> > On Tue, Jul 16, 2013 at 12:53 PM, Chris Geer <[email protected]> >> >>> wrote: >> >>> > >> >>> >> On Tue, Jul 16, 2013 at 10:32 AM, Erin Noe-Payne >> >>> >> <[email protected]>wrote: >> >>> >> >> >>> >> > Any further discussion here? I would like to start implementing >> more >> >>> >> > of the REST APIs, as it is foundational for the entire angular >> >>> >> > architecture. >> >>> >> > >> >>> >> > My understanding from Matt is that the current apis in trunk are >> >>> >> > mostly proof of concept - they are not tested and much of the >> >>> >> > functionality is just stubbed. Are any of the rest api >> implementations >> >>> >> > in the code base a good working example? Is there other >> documentation >> >>> >> > we can reference? >> >>> >> > >> >>> >> >> >>> >> I've been working on the People resource as a "reference" of how I'd >> >>> like >> >>> >> to see them done but it's still a work in progress. I need to go >> back >> >>> and >> >>> >> pull out the JSONView stuff and reimplement the "fields" concept. >> >>> Couple of >> >>> >> notes: >> >>> >> >> >>> >> - Object representations should be as flat as possible >> >>> >> and separate requests should be made to nested resources to get >> nested >> >>> >> details (i.e. if you have regions and regions/1/regionwidgets, the >> >>> regions >> >>> >> representation should not contain an array of regionwidgets) >> >>> >> >> >>> > >> >>> > I am concerned about the round trips to support this when rendering >> the >> >>> > page. With any page that has a sufficient number of gadgets, adding >> to >> >>> the >> >>> > number of requests becomes problematic. >> >>> > >> >>> >> >>> I see that rule applying to the "standard" rest endpoints for crud >> >>> operations on resources. We will have some number of special endpoints >> >>> to support frequently used operations of clients. The major example >> >>> there is the page / pages for render endpoint, which will include the >> >>> nested regions, regionwidgets, and their rpc tokens, etc. >> >>> >> >> >> >> +1 >> > >> > So my thought is that we have the standard crud endpoints for all >> > individual resources. For frequently-used read operations in which we >> > need composite data sets we will have a small number of custom >> > endpoints to serve that data. Those are read-only endpoints, they will >> > not support create / update / delete operations. >> > >> > At a time when we need one of our composite data views, such as on a >> > page load, the client will make a request and get the composite data - >> > page, regions, regionwidgets and so on. The client can decompose those >> > into the individual component resources which have corresponding >> > angular $resource services, and which talk to the standard endpoints >> > to support further crud operations on them. >> > >> > Make sense / thoughts? >> > >> >> >> >>> >> >>> > >> >>> >> - All methods should return standard HTTP codes. We should document >> >>> this >> >>> >> further on the wiki to make sure we all do the same way. >> >>> >> - We won't accept partial updates with PUT, we will eventually add >> >>> PATCH >> >>> >> to support that in the future >> >>> >> - If the "fields" query attribute isn't included in a GET then all >> >>> fields >> >>> >> are returned. >> >>> >> - What is the full meta structure we want to return? >> >>> >> >> >>> >> >> >>> >> > >> >>> >> > On Thu, Jul 11, 2013 at 5:48 PM, Erin Noe-Payne >> >>> >> > <[email protected]> wrote: >> >>> >> > > On Thu, Jul 11, 2013 at 5:02 PM, Matt Franklin < >> >>> >> [email protected]> >> >>> >> > wrote: >> >>> >> > >> +1 for every one of Chris' +1s, unless otherwise noted. >> >>> >> > >> >> >>> >> > >> On Thu, Jul 11, 2013 at 3:47 PM, Chris Geer < >> [email protected] >> >>> > >> >>> >> > wrote: >> >>> >> > >> >> >>> >> > >>> Oh boy!! :) >> >>> >> > >>> >> >>> >> > >>> Comments inline >> >>> >> > >>> >> >>> >> > >>> >> >>> >> > >>> On Thu, Jul 11, 2013 at 1:20 PM, Erin Noe-Payne < >> >>> >> > [email protected] >> >>> >> > >>> >wrote: >> >>> >> > >>> >> >>> >> > >>> > Hey All, >> >>> >> > >>> > >> >>> >> > >>> > As we are starting to look at the rest apis in more detail, >> I >> >>> would >> >>> >> > >>> > like to discuss and agree upon a consistent interface for >> our >> >>> apis. >> >>> >> > >>> > We currently have several developers interested in >> contributing >> >>> to >> >>> >> > the >> >>> >> > >>> > apis and the angular branch, and I would like to solidify >> the >> >>> >> > >>> > interface, methods, response format, etc so that we can be >> on >> >>> the >> >>> >> > same >> >>> >> > >>> > page going forward. If we can agree on an api virtualization >> >>> layer >> >>> >> > >>> > then we should be able to build against it on the server >> and on >> >>> the >> >>> >> > >>> > angular application in parallel. >> >>> >> > >>> > >> >>> >> > >>> > I'll start with a proposal and look for feedback to iterate >> from >> >>> >> > there. >> >>> >> > >>> > >> >>> >> > >>> > 1. API root url >> >>> >> > >>> > >> >>> >> > >>> > "/api". Drop support for rpc api, move from /api/rest to >> just >> >>> /api. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 - the only downside of this is that it prohibits >> implementing >> >>> over >> >>> >> > time >> >>> >> > >>> and requires a rip/replace approach of the whole system >> >>> >> > > >> >>> >> > > Well the development in trunk can continue to happen on /rest. >> >>> Angular >> >>> >> > > (aka the consuming client for most of these apis) is already >> >>> happening >> >>> >> > > in a branch, so those changes can be treated as a rip / replace >> >>> >> > > easily. >> >>> >> > > >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 2. Media Types >> >>> >> > >>> > >> >>> >> > >>> > Initially support only application/json. We can revisit >> >>> >> > >>> > application/xml as a nice-to-have. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 3. HTTP Methods >> >>> >> > >>> > >> >>> >> > >>> > GET, PUT, POST, DELETE >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 (We also need to decide if PUT can handle partial updates) >> >>> >> > >>> >> >>> >> > >> >> >>> >> > >> I say not. That is what PATCH is for, once everything >> supports it: >> >>> >> > >> http://tools.ietf.org/html/rfc5789 >> >>> >> > > >> >>> >> > > My understanding is that PUT should always be a full object >> >>> replace. A >> >>> >> > > quick search returns the suggestion to use PATCH, or to use >> POST to >> >>> a >> >>> >> > > subresource with a 303 response. >> >>> >> > > >> >>> >> > >> >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 4. Status Codes >> >>> >> > >>> > >> >>> >> > >>> > 200, 201, 400, 401, 403, 404, 500 >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 5. URL formats >> >>> >> > >>> > >> >>> >> > >>> > Use plural nouns (pages, people, widgets). Do not nest >> >>> associations >> >>> >> > >>> > beyond one level deep. For example: >> >>> >> > >>> > /pages/1/regions (ok) >> >>> >> > >>> > /pages/1/regions/2/regionwidgets (not ok) >> >>> >> > >>> > /regions/2/regionwidgets (ok) >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> I'm not a fan of this requirement. Your example is the exact >> >>> reason >> >>> >> > I'm not >> >>> >> > >>> a fan actually. In all reality, regions don't mean anything >> >>> outside a >> >>> >> > page, >> >>> >> > >>> and region widgets don't mean anything outside of a region. >> Yes, >> >>> they >> >>> >> > have >> >>> >> > >>> IDs, but in reality, those IDs should be subordinate to the >> parent >> >>> >> (so >> >>> >> > >>> there should be nothing wrong with having Page 1 with regions >> >>> [1,2] >> >>> >> and >> >>> >> > >>> Page 2 with regions [1,2]). I understand that's not how the DB >> >>> works >> >>> >> > today >> >>> >> > >>> but it's what makes the most logical sense. >> >>> >> > >>> >> >>> >> > >> >> >>> >> > >> I agree with Chris. We should not limit to a single level. >> That is >> >>> >> > counter >> >>> >> > >> to a few REST web service principles. >> >>> >> > >> >> >>> >> > > >> >>> >> > > Fair enough. In this case I guess I would just be looking for >> >>> >> > > consistency - will associations be infinitely nest-able. If not, >> >>> what >> >>> >> > > is the rule to determine where we support more or less deeply >> nested >> >>> >> > > associations. >> >>> >> > > >> >>> >> > >> >> >>> >> > >>> > >> >>> >> > >>> > 6. Response formats >> >>> >> > >>> > >> >>> >> > >>> > 6a. Wrap all responses in an object. All valid (200) >> responses >> >>> >> should >> >>> >> > >>> > be wrapped in an object that includes a "meta" object for >> >>> metadata, >> >>> >> > >>> > and a "data" object for the response body. This allows us to >> >>> >> capture >> >>> >> > >>> > or extend metadata associated with a response as needed. Any >> >>> >> metadata >> >>> >> > >>> > properties should be standardized. >> >>> >> > >>> > >> >>> >> > >>> > Example: >> >>> >> > >>> > >> >>> >> > >>> > GET /people >> >>> >> > >>> > { >> >>> >> > >>> > meta: {count: 253, limit: 10, offset: 0, ...} >> >>> >> > >>> > data: [ {id: 1, name: 'canonical', ...}, ... ] >> >>> >> > >>> > } >> >>> >> > >>> > >> >>> >> > >>> > GET /people/1 >> >>> >> > >>> > { >> >>> >> > >>> > meta: { ... } >> >>> >> > >>> > data: {id:1, name: 'canonical', ...} >> >>> >> > >>> > } >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> This really complicates a couple things, first, it means the >> GET >> >>> != >> >>> >> PUT >> >>> >> > >>> since the GET will include the meta data. Can we achieve this >> same >> >>> >> > result >> >>> >> > >>> with HTTP Headers? >> >>> >> > >>> >> >>> >> > > >> >>> >> > > We could possibly achieve the same with HTTP headers. I prefer >> the >> >>> >> > > object approach for clarity, since custom http headers are less >> >>> >> > > accessible or discoverable than object structure. I get your >> point, >> >>> >> > > but I see the wrapped object approach used commonly in major >> apis. >> >>> If >> >>> >> > > it's clearly documented and used consistently across the entire >> api >> >>> I >> >>> >> > > don't really see an issue. >> >>> >> > > >> >>> >> > >>> > >> >>> >> > >>> > 6b. Error objects. In the case of an error, the correct >> error >> >>> code >> >>> >> > >>> > should be returned. In addition, an error object should be >> >>> returned >> >>> >> > >>> > with a standardized format. Ideally including a verbose, >> >>> >> > >>> > human-readable error message for developers, and an >> >>> >> internationalized >> >>> >> > >>> > readable error message for display to end users. >> >>> >> > >>> > >> >>> >> > >>> > GET /people/25 >> >>> >> > >>> > 401 >> >>> >> > >>> > { >> >>> >> > >>> > developerMessage: 'Unauthorized. Access to this resource >> >>> requires >> >>> >> > >>> > authentication', >> >>> >> > >>> > userMessage: 'Please login', >> >>> >> > >>> > stackTrace: ... >> >>> >> > >>> > } >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 6c. Partial responses. By default all responses, whether a >> list >> >>> or >> >>> >> > >>> > individual resource, should return a full representation of >> the >> >>> >> > >>> > resources (not including security constraints). All >> endpoints >> >>> >> should >> >>> >> > >>> > support the query string parameter "fields", which accepts a >> >>> comma >> >>> >> > >>> > delimited list of fields to build a partial response. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> Hmmm.....what's funny (except for the wasted work) is this is >> how >> >>> I >> >>> >> > >>> originally built the people resource. I changed it because >> the >> >>> >> > "fields" >> >>> >> > >>> approach gets almost impossible to manage with nested >> elements (at >> >>> >> > least in >> >>> >> > >>> Java - rewrite in Ruby anyone??). I'm open to suggestions >> though. >> >>> I >> >>> >> > guess >> >>> >> > >>> we could also make a rule that the data objects shouldn't have >> >>> nested >> >>> >> > >>> elements but that is a tough rule. >> >>> >> > >>> >> >>> >> > >> >> >>> >> > >> I think the fields approach makes sense long-term; but, it is >> not >> >>> >> > critical. >> >>> >> > >> >> >>> >> > >> >> >>> >> > > >> >>> >> > > I don't really know what the implementation looks like. If you >> allow >> >>> >> > > field filtering only on properties and deliver only properties >> (i.e. >> >>> >> > > no nested objects / associations) then I would assume it is >> pretty >> >>> >> > > straightforward. >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > GET /people/1 >> >>> >> > >>> > { >> >>> >> > >>> > meta: { ... }, >> >>> >> > >>> > data: { id: 1, name: 'canonical', email: ' >> [email protected] >> >>> ', >> >>> >> > ... } >> >>> >> > >>> > } >> >>> >> > >>> > >> >>> >> > >>> > GET /people/1?fields=id,name >> >>> >> > >>> > { >> >>> >> > >>> > meta: { ... }, >> >>> >> > >>> > data: { id: 1, name: 'canonical' } >> >>> >> > >>> > } >> >>> >> > >>> > >> >>> >> > >>> > 6d. Pagination. All requests that return a list should be >> >>> >> paginated. >> >>> >> > >>> > The query string parameters "limit" and "offset" should be >> used >> >>> for >> >>> >> > >>> > pagination. On any request in which either parameter is not >> set, >> >>> >> they >> >>> >> > >>> > should default to 10 and 0 respectively. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 6e. Use camelCase for properties. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 7. Endpoints. >> >>> >> > >>> > >> >>> >> > >>> > 7a. Standard endpoints: there should be standard CRUD >> endpoints >> >>> to >> >>> >> > >>> > support each rave resource. In other words, any operation >> >>> possible >> >>> >> in >> >>> >> > >>> > rave should be possible through a rest api action. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > 7b. Special endpoints. In the case of certain client needs, >> we >> >>> can >> >>> >> > >>> > implement a small number of special endpoints to fulfill a >> >>> specific >> >>> >> > >>> > role. The primary case in point is retrieving a page for >> render, >> >>> >> > which >> >>> >> > >>> > returns a page, its regions, its regionWidgets, and their >> render >> >>> >> > data. >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >>> +1 >> >>> >> > >>> >> >>> >> > >>> > >> >>> >> > >>> > >> >>> >> > >>> > >> >>> >> > >>> > Ok, I think that's it. This is meant as a proposal only - >> we are >> >>> >> > >>> > looking for feedback to go forward. Thoughts? >> >>> >> > >>> > >> >>> >> > >>> >> >>> >> > >> >>> >> >> >>> >>
