RE: JAX-RS Request Matching Wierdness
Ah nevermind. Just read the spec again and I realized that I had misread it the first time and that CXF works as the spec says. To be honest though, after reading the JSR the right way, the algorithm it talks about actually seems a bit less functional than it could be. I would think that a initial scan of all root resource classes at startup and putting all valid resource/sub-resources into a gigantic mapping, and then filtering that map for each request would be a more robust way of doing things. Anyway, thanks for looking into this. -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 12 July 2009 20:20 To: dev@cxf.apache.org Subject: RE: JAX-RS Request Matching Wierdness Hi Gary The thing is that JAX-RS does not allow for checking on the multiple root resource classes - I think there was a discussion on cxf users list about extending the selection algorithm - I don't mind if it would actually make things simpler. Please see few more comments prefixed with S.B below. Particularly I don't understand why the use of subresources affects the complexity of response objects Thanks, Sergey -Original Message- From: Tong, Gary [mailto:gary.t...@morganstanley.com] Sent: 12 July 2009 11:52 To: dev@cxf.apache.org Subject: RE: JAX-RS Request Matching Wierdness Hi Sergey, The problems come up in a number of situations, all involving multiple service beans. The simplest case is the following: public class AWebService { @GET @Path(/a) public String a() { return a; } } public class BWebService { @GET @Path(/b) public String b() { return b; } } One of the two will work, but not both. This is of course the simplest case, but there are a number of other more concrete use cases that cause issues. For instance, if I had the following URLs: GET /user POST /user GET /user/search?params And I wanted to put the CRUD ops on UserWebService but the search stuff on a SearchWebService that uses @Path(/{type}/search) then that wouldn't work in CXF. S.B : Try @Path(/user) public class UserService {} @Path(/user/) public class SearchService {} S.B : - note the trailing '/' in SearchService. It might do the trick in other cases too Also, for instance if I had the following urls: GET /posts GET /user GET /user/{id}/posts /posts would go on PostWebService and /user would go on UserWebService, but if I wanted PostWebService to handle /user/{id}/posts as just a specialized version of /posts that would be tricky with CXF. It's doable with sub-resource locators, but then my response objects start getting complicated. S.B : I'm not quite sure why the use of subresources affects the complexity of the response objects. Can you give an example please ? Thanks, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 11 July 2009 21:28 To: dev@cxf.apache.org Subject: RE: JAX-RS Request Matching Wierdness Hi Gary So what is the concrete problem you're facing ? FYI, it is the map that sorts resource classes according a number of criteria. Another thing is that the JAX-RS selection algorithm does not have be implemented literally the way it's documented in the spec, rather the final result should be correct. So let me know please what exactly is happening in your case Thanks, Sergey -Original Message- From: Tong, Gary [mailto:gary.t...@morganstanley.com] Sent: 11 July 2009 16:57 To: dev@cxf.apache.org Subject: JAX-RS Request Matching Wierdness Hello, Hey guys, just fyi, CXF's jax-rs doesn't do request matching correctly. According to JSR 311 in section 3.7.2, the jax-rs server is supposed to apply a series of steps to determine which URL to use for the request. Instead, CXF applies a path filter at the class level, and then returns the first entry it finds. Specifically the code that does this is in JAXRSUtils.selectResourceClass: if (!candidateList.isEmpty()) { Map.EntryClassResourceInfo, MultivaluedMapString, String firstEntry = candidateList.entrySet().iterator().next(); values.putAll(firstEntry.getValue()); return firstEntry.getKey(); } Not sure if you guys know about this. Cheers, Gary -- NOTICE: If received in error, please destroy, and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. We may monitor and store emails to the extent permitted by applicable law. -- NOTICE: If received in error, please destroy, and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. We may monitor and store emails to the extent permitted by applicable law
RE: JAX-RS Request Matching Wierdness
Hi Sergey, The problems come up in a number of situations, all involving multiple service beans. The simplest case is the following: public class AWebService { @GET @Path(/a) public String a() { return a; } } public class BWebService { @GET @Path(/b) public String b() { return b; } } One of the two will work, but not both. This is of course the simplest case, but there are a number of other more concrete use cases that cause issues. For instance, if I had the following URLs: GET /user POST /user GET /user/search?params And I wanted to put the CRUD ops on UserWebService but the search stuff on a SearchWebService that uses @Path(/{type}/search) then that wouldn't work in CXF. Also, for instance if I had the following urls: GET /posts GET /user GET /user/{id}/posts /posts would go on PostWebService and /user would go on UserWebService, but if I wanted PostWebService to handle /user/{id}/posts as just a specialized version of /posts that would be tricky with CXF. It's doable with sub-resource locators, but then my response objects start getting complicated. Thanks, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 11 July 2009 21:28 To: dev@cxf.apache.org Subject: RE: JAX-RS Request Matching Wierdness Hi Gary So what is the concrete problem you're facing ? FYI, it is the map that sorts resource classes according a number of criteria. Another thing is that the JAX-RS selection algorithm does not have be implemented literally the way it's documented in the spec, rather the final result should be correct. So let me know please what exactly is happening in your case Thanks, Sergey -Original Message- From: Tong, Gary [mailto:gary.t...@morganstanley.com] Sent: 11 July 2009 16:57 To: dev@cxf.apache.org Subject: JAX-RS Request Matching Wierdness Hello, Hey guys, just fyi, CXF's jax-rs doesn't do request matching correctly. According to JSR 311 in section 3.7.2, the jax-rs server is supposed to apply a series of steps to determine which URL to use for the request. Instead, CXF applies a path filter at the class level, and then returns the first entry it finds. Specifically the code that does this is in JAXRSUtils.selectResourceClass: if (!candidateList.isEmpty()) { Map.EntryClassResourceInfo, MultivaluedMapString, String firstEntry = candidateList.entrySet().iterator().next(); values.putAll(firstEntry.getValue()); return firstEntry.getKey(); } Not sure if you guys know about this. Cheers, Gary -- NOTICE: If received in error, please destroy, and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. We may monitor and store emails to the extent permitted by applicable law. -- NOTICE: If received in error, please destroy, and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. We may monitor and store emails to the extent permitted by applicable law.
JAX-RS Request Matching Wierdness
Hello, Hey guys, just fyi, CXF's jax-rs doesn't do request matching correctly. According to JSR 311 in section 3.7.2, the jax-rs server is supposed to apply a series of steps to determine which URL to use for the request. Instead, CXF applies a path filter at the class level, and then returns the first entry it finds. Specifically the code that does this is in JAXRSUtils.selectResourceClass: if (!candidateList.isEmpty()) { Map.EntryClassResourceInfo, MultivaluedMapString, String firstEntry = candidateList.entrySet().iterator().next(); values.putAll(firstEntry.getValue()); return firstEntry.getKey(); } Not sure if you guys know about this. Cheers, Gary -- NOTICE: If received in error, please destroy, and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. We may monitor and store emails to the extent permitted by applicable law.
RE: JSON in CXF
Would you want to give this to someone from GSoC? This could actually be a pretty sweet project. -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 07 April 2009 12:14 To: dev@cxf.apache.org Subject: Re: JSON in CXF Hi Gary If you give me until next week I should be able to package something together and send it to you. it would be super, take your time please... Rewriting Sun libraries? Working with JSON? Hells yeah. that's the right attitude :-). cheers, Sergey - Original Message - From: Tong, Gary (IDEAS) gary.t...@morganstanley.com To: dev@cxf.apache.org Sent: Tuesday, April 07, 2009 8:53 AM Subject: RE: JSON in CXF Hi Sergey, If you give me until next week I should be able to package something together and send it to you. Alternatively, this would be a great project for GSoC, if it's not too late to submit projects. Rewriting Sun libraries? Working with JSON? Hells yeah. Cheers, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 06 April 2009 12:01 To: dev@cxf.apache.org Subject: Re: JSON in CXF Hi Gary I ended up writing my own converter for JSON that uses its own annotations seperate from JAXB. It's a pretty quick implementation, and only does what I need it to do. It depends on the JSON objects from json.org, which are also included in Jettison under a different package. The annotations can be used alongside JAXB like so: @XmlRootElement(name = response) @JsonObject public class MyResponse { @XmlAttribute @JsonField private boolean success; @XmlElement(name = msg) @JsonField(name = msg) private String message; @XmlElementWrapper(name = errors) @XmlElement(name = error) @JsonField(name = errors, required = true) private ListString errors; ... } Would you be interested in updating the existing CXF JSONProvider (the one based on Jettison) for it to support @JsonObject/etc annotations ? I was about to do it myself but given my JSON experience (not great so to say) I thought I would ping you first :-) we can introduce a new package, org.apache.cxf.jaxrs.providers.json, or org.apache.cxf.jaxrs.ext.json, and add these annotations there, and then rely on the fact Jettison ships JSonObject/etc... cheers, Sergey This will produce this JSON: {success: true, msg: Test Message, errors: [a, b]} And this XML: response success=truemsgTest Message/msgerrorserrora/errorerrorb/error/errors/respo nse Since this was written only for personal use, it's a fair bit aways from being a full-featured library. Stuff that needs to be done before public consumption: 1) Two-way serialization. Currently it's only bean - JSON but not the other way around. 2) Reflection caching. Currently all reflection happens in the middle of serialization. Breaking it up into reflection + serialization phases as JAXB does it would speed things up considerably. 3) Ability to switch between field/method accessors (currently it only reads fields) As well as some features that could be really useful such as: 1) Pluggable annotation adapters that can be used to read directly from JAXB annotations 2) Type adapters that will allow custom marshalling/unmarshalling, although this could also be done via getters/setters What's the interest level in putting something like this into CXF? Cheers, Gary -- NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. -- NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error.
Possibly retarded question
Is there any value in allowing a method to respond to both GET and POST requests? Currently something like: class Foo { @GET @POST public String test() {...} } Only responds to @GET but does not respond to @POST. I agree that conceptually, @GET and @POST should be completely different methods. This is just something random that came up when working on our application. One of the clients that we're using sends GET in some situations and POST in other situations. As other libraries generally handle GETs and POSTs interchangably, this wasn't an issue until we migrated this to CXF. In any case, it was easy enough to work around this, and I'm not even if I think it should be changed. Mostly just curious to hear the team's thoughts and see if this issue has come up before. Cheers, Gary -- NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error.
RE: ProviderFactory singleton?
Proof of Concept Implementation: ProviderFactory: public static ProviderFactory getInstance() { return getInstance(/); } public static ProviderFactory getInstance(String baseAddress) { Bus bus = BusFactory.getThreadDefaultBus(); ProviderFactoryMap providerFactoryMap = bus.getExtension(ProviderFactoryMap.class); if (providerFactoryMap == null) { providerFactoryMap = new ProviderFactoryMap(); bus.setExtension(providerFactoryMap, ProviderFactoryMap.class); } ProviderFactory pf = null; synchronized (ProviderFactoryMap.class) { pf = providerFactoryMap.get(baseAddress); if (pf == null) { pf = new ProviderFactory(); providerFactoryMap.put(baseAddress, pf); } } return pf; } ProviderFactoryMap: public class ProviderFactoryMap extends HashMapString, ProviderFactory { private static final long serialVersionUID = 1L; } Quick dirty way of doing it. Passes my tests. Almost definitely not the best way of implementing it though. It's not thread safe, and at the very least, seems like we should explicitly pass the bus around instead of using the thread local. It looks like creating something like ProviderManagerImpl would fit conventions better. Have the code checked out now. Can work on a patch if there is interest. Regards, Gary -Original Message- From: Daniel Kulp [mailto:dk...@apache.org] Sent: 09 March 2009 18:53 To: dev@cxf.apache.org Cc: Tong, Gary (IDEAS) Subject: Re: ProviderFactory singleton? It's not just OSGi as well. One way of setting up CXF with tomcat is to put the CXF jars into the tomcat shared/lib directory and then deploy 100 wars/applications each using CXF with their own CXF servlet. In that case, anything static gets shared between all 100 services, although each application would have it's own bus and stuff. Every single one of those 100 apps may have a service names /foo based off of it's base. They obviously need to be resolved correctly to the correct factories. This is actually how I setup the JAX-WS tck to run. One more note: by sticking the factory onto the endpoint, it gets properly garbage collected on undeploy. The current setup stores all the factories in a map. They NEVER get removed. Thus, undeploying the app would result in memory leaks and such.That's one of the major advantages to popping the data onto the endpoint object. It pretty much gets cleaned up automatically. For a while, ws-rm/ws-a did the same thing (store in static maps). We had problems getting everything cleaned up all the time. Moved it all to storing it on the endpoint, problem solved. Dan On Mon March 9 2009 6:54:38 am Tong, Gary (IDEAS) wrote: Hi Sergey, I've done a bit of work to allow two overlapping addresses to be deployed side-by-side. It mostly involes doing all the configuration within a child context. Small change really, which works fine except for the bit about the providers. I think Dan is talking about the same deployment issues as I am. In OSGi you could have two bundles that both use CXF JAX-RS that end up stomping all over each other's singletons. This really shouldn't happen, but some OSGi (most?) containers allow for shared classloading in one fashion or another, which could cause issues. Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 09 March 2009 10:38 To: Daniel Kulp; dev@cxf.apache.org Subject: Re: ProviderFactory singleton? Hi, I wish someone explained me why things will get worse in OSGI, with ProviderFactory.getInstance(). There's a direct relationship between any given endpoint and a ProviderFactory instance and ProviderFactory does not rely itself on some FactoryFinders, etc...It's all quite straightforward really there and at the moment I don't see why things will fail in OSGI, given that in fact I've seen CXF JAXRS working in OSGI, though withougt multiple endpoints being involved. Is it because ProviderFactory has static fields ? Are we talking here about multiple CXF JAXRS bundles being loaded ? I guess we will have multiple versions in this case so I don't see why classloading issues will arise in such cases. What is it that I'm missing ? It simply encapsulates the requirement try user providers first, delegate to the defulat ones as the last resort. Each module has no knowledge of any other module its deployed next to, which is why multiple modules may easily have overlapping addresses. this is more intertesting to me really, as it's about the concrete problem which might occur at the deployment time. I honestly did not know that it were possible to have multiple jaxrs:endpoints with identical address values working even only with default providers involved (note, overlapping addresses, as in say '/bar' and '/' should work fine with per-endpoint
RE: ProviderFactory singleton?
Hi Sergey, I've done a bit of work to allow two overlapping addresses to be deployed side-by-side. It mostly involes doing all the configuration within a child context. Small change really, which works fine except for the bit about the providers. I think Dan is talking about the same deployment issues as I am. In OSGi you could have two bundles that both use CXF JAX-RS that end up stomping all over each other's singletons. This really shouldn't happen, but some OSGi (most?) containers allow for shared classloading in one fashion or another, which could cause issues. Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 09 March 2009 10:38 To: Daniel Kulp; dev@cxf.apache.org Subject: Re: ProviderFactory singleton? Hi, I wish someone explained me why things will get worse in OSGI, with ProviderFactory.getInstance(). There's a direct relationship between any given endpoint and a ProviderFactory instance and ProviderFactory does not rely itself on some FactoryFinders, etc...It's all quite straightforward really there and at the moment I don't see why things will fail in OSGI, given that in fact I've seen CXF JAXRS working in OSGI, though withougt multiple endpoints being involved. Is it because ProviderFactory has static fields ? Are we talking here about multiple CXF JAXRS bundles being loaded ? I guess we will have multiple versions in this case so I don't see why classloading issues will arise in such cases. What is it that I'm missing ? It simply encapsulates the requirement try user providers first, delegate to the defulat ones as the last resort. Each module has no knowledge of any other module its deployed next to, which is why multiple modules may easily have overlapping addresses. this is more intertesting to me really, as it's about the concrete problem which might occur at the deployment time. I honestly did not know that it were possible to have multiple jaxrs:endpoints with identical address values working even only with default providers involved (note, overlapping addresses, as in say '/bar' and '/' should work fine with per-endpoint providers), with CXF servlets providing the needed uniqueness to the actual adresses. I'll need to think how it can be accomodated - I'm just not sure yet how :-). Perhaps the validation rules invoked at the deployment time would ensure the uniqueness of jaxrs:endpoint addresses - but that depends on the availability of such rules - and again - if things are expected to work with multiple endpoints having identical @adress values then CXF JAXRS has to ensure per-endpoint providers don't clash with eath other. thanks, Sergey On Fri March 6 2009 7:12:51 am Sergey Beryozkin wrote: One issue is that ProviderFactory is also used at the moment in the client api, Doesn't the Client API also use the Bus? Could/Should it? (example: does it currently use the HTTPConduit/transport?) If so, hanging this off the bus is probably the best idea.I definitely agree that Singletons are a really bad idea. It actually will get worse with OSGi as classloaders and stuff are different so that singleton could end up holding onto things and exposing things from other applications. Dan though an endpoint info representation is also created there. So we might in principle have a thread local endpoint info storage, such that ProviderFactory.getInstance() would use thread-local endpoint info as a key to get the actual ProviderFactory instance. Perhaps a simpler option is to just keep a ProviderFactory instance with a given Endpoint. I need to think about it - it's getting a bit tight now, as 2.2 is likely to go out quite soon so such a change may not make it into the trunk say next week... But do you think the possible update as suggested above would not be quite acceptable in your case, even as a workaround? I'd like to understand better when it may be unrealistic to ensure that different endpoints have their own addresses : perhaps there're policies on which uri patterns go to web.xml or to resource classes, etc ? Cheers, Sergey -Original Message- From: Tong, Gary (IDEAS) [mailto:gary.t...@morganstanley.com] Sent: 06 March 2009 11:44 To: dev@cxf.apache.org Subject: RE: ProviderFactory singleton? Is it when you have multiple CXF servlets, each of them referencing different spring configuration files ? Yes exactly. -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 06 March 2009 10:18 To: dev@cxf.apache.org Subject: RE: ProviderFactory singleton? Hi Gary I've updated a bit ProviderFactory on the trunk, there's a default ProviderFactory which hosts the default providers and a ProviderFactory instance per every endpoint address, for ex, ProviderFactory.getInstance() and ProviderFactory.getInstance(/) would return an instance keyed by '/', etc. So I thought that an endpoint address, as specified
RE: ProviderFactory singleton?
I guess I just find that conceptually awkward. Our use case is that we have a single war that hosts a variety of CXF services imported from module jars. Each module is responsible for defining their own CXF server, and the war creates one CXF servlet for each module and places each one on their own context path. The war also makes certain common services available to each module via spring, which allows common singleton-type objects to be shared across multiple modules (things like datasources, caches, threadpools, etc) Each module has no knowledge of any other module its deployed next to, which is why multiple modules may easily have overlapping addresses. We first came upon this issue when different modules defined different error handlers, which worked in each module independently, but broke when deployed. As a spring-based application, I suppose the assumption is that any singletons in the system would be spring-style singletons, isolated at the bean factory level. Not a show-stopper for us, but since JAX-RS is a very nice easy-to-use library, as usage spreads I wouldn't be surprised if this issue comes up again as CXF JAX-RS is deployed into wierder and wierder containers. An OSGi container with shared classloading comes to mind as an environment where this would break. -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 06 March 2009 12:13 To: dev@cxf.apache.org Subject: RE: ProviderFactory singleton? OK. I'm not sure yet what would be the best way to tackle it. How restrictive would it be if we said that every jaxrs:endpoint should have its own unique address ? For ex, at the moment : CXFServlet1 : /1/* links to beans1.xml CXFServlet2 : /2/* links to beans2.xml jaxrs:server/@adress='/' in both beans1.xml and beans2.xml, presumably relying on separate resource classes, say the one in beans1.xml uses Resource.class with @Path(/r1) and the other one uses Resource2.class with @Path(/r2) So one option would be to move /r1 and /r2 out of the resource classes into corresponding jaxrs:server/@adress(es) and just have @Path(/) for both resource classes. One issue is that ProviderFactory is also used at the moment in the client api, though an endpoint info representation is also created there. So we might in principle have a thread local endpoint info storage, such that ProviderFactory.getInstance() would use thread-local endpoint info as a key to get the actual ProviderFactory instance. Perhaps a simpler option is to just keep a ProviderFactory instance with a given Endpoint. I need to think about it - it's getting a bit tight now, as 2.2 is likely to go out quite soon so such a change may not make it into the trunk say next week... But do you think the possible update as suggested above would not be quite acceptable in your case, even as a workaround? I'd like to understand better when it may be unrealistic to ensure that different endpoints have their own addresses : perhaps there're policies on which uri patterns go to web.xml or to resource classes, etc ? Cheers, Sergey -Original Message- From: Tong, Gary (IDEAS) [mailto:gary.t...@morganstanley.com] Sent: 06 March 2009 11:44 To: dev@cxf.apache.org Subject: RE: ProviderFactory singleton? Is it when you have multiple CXF servlets, each of them referencing different spring configuration files ? Yes exactly. -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 06 March 2009 10:18 To: dev@cxf.apache.org Subject: RE: ProviderFactory singleton? Hi Gary I've updated a bit ProviderFactory on the trunk, there's a default ProviderFactory which hosts the default providers and a ProviderFactory instance per every endpoint address, for ex, ProviderFactory.getInstance() and ProviderFactory.getInstance(/) would return an instance keyed by '/', etc. So I thought that an endpoint address, as specified by jaxrs:endpoint, would be a unique enough key for ProviderFactory instances. Do you have the case where multiple endpoints share the same jaxrs:endpoint/@address ? Is it when you have multiple CXF servlets, each of them referencing different spring configuration files ? Cheers, Sergey -Original Message- From: Tong, Gary (IDEAS) [mailto:gary.t...@morganstanley.com] Sent: 06 March 2009 09:14 To: dev@cxf.apache.org Subject: ProviderFactory singleton? Been looking through the code, and why is ProviderFactory a singleton? I would think it would be tied to a bus or a server. It differentiates by address, but currently I'm working on something with two side-by-side CXF servlets that load completely different CXF configurations. In this case, providers declared in one server are bleeding into the other because the ProviderFactory uses a singleton. Worth fixing? Also, are there any other uses of singletons in the system that maybe should be looked at? Cheers, Gary
RE: CXF dual-servlet issues
As far as I can tell, this issue is caused by RequestPreprocessor.handleExtensionMappings private void handleExtensionMappings(Message m, UriInfo uriInfo) { String path = uriInfo.getPath(false); for (Map.Entry?, ? entry : extensionMappings.entrySet()) { if (path.endsWith(. + entry.getKey().toString())) { updateAcceptTypeHeader(m, entry.getValue().toString()); updatePath(m, path, entry.getKey().toString()); break; } } } UriInfoImpl.getPath takes the REQUEST_URI from message (/foo/foo/response.xml), the base address (/foo/), and sends it to HttpUtils.getPathToMatch(String, String, boolean) which strips the base address from the URI and returns /foo/response.xml. This is then passed through the extension mappings bit. If a match is found, then the Accept header is updated, as is the path. The problem comes when the path is updated. Previously, the path was /foo/foo/response.xml. However, as uriInfo.getPath strips off the first /foo/ and returns /foo/response.xml, when updatePath is called, it ends up updating the REQUEST_URI to /foo/response instead of /foo/foo/response as it should. Any number of ways to fix this, I suppose. One way may be to add an updatePath method to HttpUtils and switch RequestPreprocessor.updatePath to use it. public static void updatePath(Message m, String path) { String baseAddress = getBaseAddress(m); boolean pathSlash = path.startsWith(/); boolean baseSlash = path.endsWith(/); if (pathSlash baseSlash) { path = path.substring(1); } else if (!pathSlash !baseSlash) { path = / + path; } m.put(Message.REQUEST_URI, baseAddress + path); } I'd submit a patch + unit tests, but I can't access the source repo from here. Cheers, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 20 February 2009 19:16 To: dev@cxf.apache.org Subject: Re: CXF dual-servlet issues I'm impressed :-) Looks like it's all down to a url pattern you choose :-) Yeah - I'm too exhausted :-) too at the moment so will check early next week. I'm about to complete the client api stuff for 2.2. and will dedicate the remaining time to addressing the various issues raised recently Cheers, Sergey - Original Message - From: Tong, Gary (FID) gary.t...@morganstanley.com To: dev@cxf.apache.org Sent: Friday, February 20, 2009 6:59 PM Subject: CXF dual-servlet issues Will investigate more on Monday, but this is currently breaking in CXF 2.1.4: context.xml: ?xml version=1.0? beans xmlns=http://www.springframework.org/schema/beans; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xmlns:jaxrs=http://cxf.apache.org/jaxrs; xsi:schemaLocation= http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd; import resource=classpath:META-INF/cxf/cxf.xml / import resource=classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml / import resource=classpath:META-INF/cxf/cxf-servlet.xml / jaxrs:server id=cxfMapping address=/ jaxrs:serviceBeans bean class=sandbox.cxf.controller.FooController/ /jaxrs:serviceBeans jaxrs:extensionMappings entry key=json value=application/json/ entry key=xml value=application/xml/ /jaxrs:extensionMappings /jaxrs:server /beans web.xml: ?xml version=1.0? web-app xmlns=http://java.sun.com/xml/ns/j2ee; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd; version=2.4 context-param param-namecontextConfigLocation/param-name param-valueWEB-INF/context.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener servlet servlet-namecxf/servlet-name servlet-classorg.apache.cxf.transport.servlet.CXFServlet/servlet-class load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namecxf/servlet-name url-pattern/foo/*/url-pattern /servlet-mapping /web-app FooController.java: @Path(/foo/) public class FooController { @GET @Path(/text/) @ProduceMime(text/plain) public String text() { return foo; } @GET @Path(/response/) public Response response() { return new Response(foo); } } Response.java: @XmlRootElement(name = response) @XmlAccessorType(XmlAccessType.FIELD) public class Response { @XmlElement(name = msg) private String message; public Response() { } public Response(String message) { this.message = message; } /** * @return the message */ public
CXF dual-servlet issues
Will investigate more on Monday, but this is currently breaking in CXF 2.1.4: context.xml: ?xml version=1.0? beans xmlns=http://www.springframework.org/schema/beans; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xmlns:jaxrs=http://cxf.apache.org/jaxrs; xsi:schemaLocation= http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd; import resource=classpath:META-INF/cxf/cxf.xml / import resource=classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml / import resource=classpath:META-INF/cxf/cxf-servlet.xml / jaxrs:server id=cxfMapping address=/ jaxrs:serviceBeans bean class=sandbox.cxf.controller.FooController/ /jaxrs:serviceBeans jaxrs:extensionMappings entry key=json value=application/json/ entry key=xml value=application/xml/ /jaxrs:extensionMappings /jaxrs:server /beans web.xml: ?xml version=1.0? web-app xmlns=http://java.sun.com/xml/ns/j2ee; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd; version=2.4 context-param param-namecontextConfigLocation/param-name param-valueWEB-INF/context.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener servlet servlet-namecxf/servlet-name servlet-classorg.apache.cxf.transport.servlet.CXFServlet/servlet-class load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namecxf/servlet-name url-pattern/foo/*/url-pattern /servlet-mapping /web-app FooController.java: @Path(/foo/) public class FooController { @GET @Path(/text/) @ProduceMime(text/plain) public String text() { return foo; } @GET @Path(/response/) public Response response() { return new Response(foo); } } Response.java: @XmlRootElement(name = response) @XmlAccessorType(XmlAccessType.FIELD) public class Response { @XmlElement(name = msg) private String message; public Response() { } public Response(String message) { this.message = message; } /** * @return the message */ public String getMessage() { return message; } /** * @param message *the message to set */ public void setMessage(String message) { this.message = message; } } Results: GET /foo/foo/text - 200 foo GET /foo/foo/response.xml - 404 GET /foo/foo/response.json - 404 But change web.xml from servlet-mapping servlet-namecxf/servlet-name url-pattern/foo/*/url-pattern /servlet-mapping To servlet-mapping servlet-namecxf/servlet-name url-pattern/wtf/*/url-pattern /servlet-mapping GET /wtf/foo/text - 200 foo GET /wtf/foo/response.xml - 200 ... GET /wtf/foo/response.json - 200 ... Bizarre... -- This is not an offer (or solicitation of an offer) to buy/sell the securities/instruments mentioned or an official confirmation. Morgan Stanley may deal as principal in or own or act as market maker for securities/instruments mentioned or may advise the issuers. This is not research and is not from MS Research but it may refer to a research analyst/research report. Unless indicated, these views are the author’s and may differ from those of Morgan Stanley research or others in the Firm. We do not represent this is accurate or complete and we may not update this. Past performance is not indicative of future returns. For additional information, research reports and important disclosures, contact me or see https://secure.ms.com/servlet/cls. You should not use e-mail to request, authorize or effect the purchase or sale of any security or instrument, to send transfer instructions, or to effect any other transactions. We cannot guarantee that any such requests received via e-mail will be processed in a timely manner. This communication is solely for the addressee(s) and may contain confidential information. We do not waive confidentiality by mistransmission. Contact me if you do not wish to receive these communications. In the UK, this communication is directed in the UK to those persons who are professional and eligible counterparties (as defined in the UK Financial Services Authority’s rules).
JSON in CXF
Hi guys, I really like how CXF provides both JSON and XML out of the box. However, after working with the JSON serializer a bit, it's obvious that the JAXB annotations translate poorly to JSON, and that while you have great control over XML via JAXB, JSON via JAXB definitely leaves something to be desired. Do you guys know of any jaxb-quality, annotation-driven JSON serializers? Cheers, Gary -- This is not an offer (or solicitation of an offer) to buy/sell the securities/instruments mentioned or an official confirmation. Morgan Stanley may deal as principal in or own or act as market maker for securities/instruments mentioned or may advise the issuers. This is not research and is not from MS Research but it may refer to a research analyst/research report. Unless indicated, these views are the author’s and may differ from those of Morgan Stanley research or others in the Firm. We do not represent this is accurate or complete and we may not update this. Past performance is not indicative of future returns. For additional information, research reports and important disclosures, contact me or see https://secure.ms.com/servlet/cls. You should not use e-mail to request, authorize or effect the purchase or sale of any security or instrument, to send transfer instructions, or to effect any other transactions. We cannot guarantee that any such requests received via e-mail will be processed in a timely manner. This communication is solely for the addressee(s) and may contain confidential information. We do not waive confidentiality by mistransmission. Contact me if you do not wish to receive these communications. In the UK, this communication is directed in the UK to those persons who are professional and eligible counterparties (as defined in the UK Financial Services Authority’s rules).
RE: JSON in CXF
I think it's a limitation of the underlying JSON library. Something like: @XmlRootElement public class Foo { @XmlElementWrapper(name=values) @XmlElement(name=value) private ListString values } Gives XML like: foo values valuefoo/value valuebar/value /values /foo And json like: {foo: {values: {value: [foo, bar]}}} Whereas really, if this is an API that you want to publicize, you really want: {values: [foo, bar]} Seems like the JSON is generated via JAXB and an XMLStreamWriter, which unfortunately is too limited to provide real control over the JSON. Thanks, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 10 February 2009 10:48 To: dev@cxf.apache.org Subject: Re: JSON in CXF Hi Gary JSON via JAXB definitely leaves something to be desired. Do you reckon it's the limitations of the underlying JSON library that we use (Jettison) or do you refer to the insufficient number of hooks for our JSON JAXRS reader/writer whiich would help in producing a better quality JSON ? Can you post some examples please - I hope it will help us to improve what we have Thanks, Sergey Hi guys, I really like how CXF provides both JSON and XML out of the box. However, after working with the JSON serializer a bit, it's obvious that the JAXB annotations translate poorly to JSON, and that while you have great control over XML via JAXB, JSON via JAXB definitely leaves something to be desired. Do you guys know of any jaxb-quality, annotation-driven JSON serializers? Cheers, Gary -- This is not an offer (or solicitation of an offer) to buy/sell the securities/instruments mentioned or an official confirmation. Morgan Stanley may deal as principal in or own or act as market maker for securities/instruments mentioned or may advise the issuers. This is not research and is not from MS Research but it may refer to a research analyst/research report. Unless indicated, these views are the author's and may differ from those of Morgan Stanley research or others in the Firm. We do not represent this is accurate or complete and we may not update this. Past performance is not indicative of future returns. For additional information, research reports and important disclosures, contact me or see https://secure.ms.com/servlet/cls. You should not use e-mail to request, authorize or effect the purchase or sale of any security or instrument, to send transfer instructions, or to effect any other transactions. We cannot guarantee that any such requests received via e-mail will be processed in a timely manner. This communication is solely for the addressee(s) and may contain confidential information. We do not waive confidentiality by mistransmission. Contact me if you do not wish to receive these communications. In the UK, this communication is directed in the UK to those persons who are professional and eligible counterparties (as defined in the UK Financial Services Authority's rules). -- This is not an offer (or solicitation of an offer) to buy/sell the securities/instruments mentioned or an official confirmation. Morgan Stanley may deal as principal in or own or act as market maker for securities/instruments mentioned or may advise the issuers. This is not research and is not from MS Research but it may refer to a research analyst/research report. Unless indicated, these views are the author’s and may differ from those of Morgan Stanley research or others in the Firm. We do not represent this is accurate or complete and we may not update this. Past performance is not indicative of future returns. For additional information, research reports and important disclosures, contact me or see https://secure.ms.com/servlet/cls. You should not use e-mail to request, authorize or effect the purchase or sale of any security or instrument, to send transfer instructions, or to effect any other transactions. We cannot guarantee that any such requests received via e-mail will be processed in a timely manner. This communication is solely for the addressee(s) and may contain confidential information. We do not waive confidentiality by mistransmission. Contact me if you do not wish to receive these communications. In the UK, this communication is directed in the UK to those persons who are professional and eligible counterparties (as defined in the UK Financial Services Authority’s rules).
RE: JSON in CXF
Hi Guys, Thanks for the quick responses. Here's an example of what I'm talking about. Let's say I wanted to expose an API for blog posts, and I wanted reasonable responses in both XML and JSON format. The XML should probably look like: post titleMy Blog Post/title textTest Blog/title authorSome Guy/author comments comment authorSome Other Guy/author textTest Comment/text /comment /comments /post And the JSON should probably look like: { title: My Blog Post, text: Test Blog, author: Some Guy, comments: [{ author: Some Other Guy, text: Test Comment }] } The bean should look like: class Post { private String title; private String text; private String author; private ListComment comments; ... } These are just the resonably intuitive response formats for each format. The problem is that the packaged providers (JSONProvider and JAXBElementProvider) cannot provide both formats from the same bean without some ugly hacks. Getting the bean to output the correct XML means that you end up with JSON that looks like this: { title: My Blog Post, text: Test Blog, author: Some Guy, comments: { comment: [{ author: Some Other Guy, text: Test Comment }] } } And getting the bean to output the correct JSON means that you end up with XML that looks like this: post titleMy Blog Post/title textTest Blog/title authorSome Guy/author comment authorSome Other Guy/author textTest Comment/text /comment /post The problem is that because the JSON provider piggybacks off the JAXB XML annotations, you only get indirect control of the way the bean is marshalled, and if you need tight control over both the XML and JSON representations, things get either messy or impossible. My solution to this is to replace the standard JSON provider with my own implementation. I was curious about 2 things 1) Do you guys know of any jaxb-quality, annotation-driven JSON serializers? 2) Are you guys interested in replacing the existing JSON provider, or making an alternative one available that allows a bit more control over how the JSON is rendered? Thanks, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 10 February 2009 13:23 To: Sergey Beryozkin; dev@cxf.apache.org Subject: Re: JSON in CXF I think going with ContextResolverJAXBContext may be a workable workaround, but I'd like to ask for some clarification in meantime... I've talked to Dejan who is a Jettison commiter and perhaps Jettison can get enhanced a bit in some time to deal with such cases natively with the help of some additional configuration (which will obvioulsy be available at a JSONProvider level). However we'd like to get some additional clarifications Gives XML like: foo values valuefoo/value valuebar/value /values /foo And json like: {foo: {values: {value: [foo, bar]}}} Whereas really, if this is an API that you want to publicize, you really want: {values: [foo, bar]} Gary - is it a typical requirement for developers producing JSON ? How it can be characterized ? We can see that a root element needs to be dropped and names of children of an element marked with @XmlElementWrapper need to be ignored too. Can you please explain a bit more ? Any links will be appreciated. Likewise, few more samples with slightly different object graphs but showing the same pattern in action would help us to come up with a new feature enhancement request for Jettison Thanks, Sergey - Original Message - From: Tong, Gary (FID) gary.t...@morganstanley.com To: dev@cxf.apache.org Sent: Tuesday, February 10, 2009 11:24 AM Subject: RE: JSON in CXF I think it's a limitation of the underlying JSON library. Something like: @XmlRootElement public class Foo { @XmlElementWrapper(name=values) @XmlElement(name=value) private ListString values } Gives XML like: foo values valuefoo/value valuebar/value /values /foo And json like: {foo: {values: {value: [foo, bar]}}} Whereas really, if this is an API that you want to publicize, you really want: {values: [foo, bar]} Seems like the JSON is generated via JAXB and an XMLStreamWriter, which unfortunately is too limited to provide real control over the JSON. Thanks, Gary -Original Message- From: Sergey Beryozkin [mailto:sbery...@progress.com] Sent: 10 February 2009 10:48 To: dev@cxf.apache.org Subject: Re: JSON in CXF Hi Gary JSON via JAXB definitely leaves something to be desired. Do you reckon it's the limitations of the underlying JSON library that we use (Jettison) or do you refer to the insufficient number of hooks for our JSON JAXRS reader/writer whiich would help in producing a better quality JSON ? Can you post some examples please - I hope it will help us to improve what we have Thanks, Sergey Hi guys, I really like how CXF provides both JSON and XML out of the box
Issue with multiple CXF servlets (and proposed fix)
Hello, I'm having issues with creating multiple CXFServlets. I'm trying to insantiate 2 independent CXF servlets and deploy them at different URLs. The relevant part of the web.xml looks like: servlet servlet-nametest/servlet-name servlet-classorg.apache.cxf.transport.servlet.CXFServlet/servlet-class load-on-startup1/load-on-startup init-param param-nameconfig-location/param-name param-value/WEB-INF/test-servlet.xml/param-value /init-param /servlet servlet-mapping servlet-nametest/servlet-name url-pattern/t/*/url-pattern /servlet-mapping servlet servlet-namefoo/servlet-name servlet-classorg.apache.cxf.transport.servlet.CXFServlet/servlet-class load-on-startup1/load-on-startup init-param param-nameconfig-location/param-name param-value/WEB-INF/foo-servlet.xml/param-value /init-param /servlet servlet-mapping servlet-namefoo/servlet-name url-pattern/f/*/url-pattern /servlet-mapping This, unfortunately, doesn't work. My test-servlet.xml file looks like: ?xml version=1.0? beans xmlns=http://www.springframework.org/schema/beans; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xmlns:jaxrs=http://cxf.apache.org/jaxrs; xsi:schemaLocation= http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd; import resource=classpath:META-INF/cxf/cxf.xml / import resource=classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml / import resource=classpath:META-INF/cxf/cxf-servlet.xml / jaxrs:server id=cxfMapping address=/ jaxrs:serviceBeans ref bean=testController/ /jaxrs:serviceBeans jaxrs:extensionMappings entry key=xml value=application/xml / /jaxrs:extensionMappings /jaxrs:server bean id=testController class=test.TestController/ /beans And foo-servlet.xml looks much the same. This configuration gives me a No service was found. response. However, if I move the import statements to the base spring application context, both the test and foo servlets end up serving up test-servlet.xml and foo-servlet.xml gets ignored. As far as I can tell, this problem occurs because the configs specified in config-location aren't loaded until the majority of the servlet has been initialized. Because of this, most of the settings in test-servlet.xml and foo-servlet.xml are ignored during initialization. The order of initialization in CXFServlet seems to be: 1. Find the spring app context. 2. Create a new bus based on the app context. 3. Set up the servlet transport factory 4. Create the controller 5. Load the additional configuration from the config-location servlet param My proposed fix is to change the order of initialization to: 1. Find the spring app context. 2. Load the additional configuration from the config-location servlet param 3. Create a new bus based on the new child context (or original spring app context if there is no additional configuration) 4. Set up the servlet transport factory 5. Create the controller The attached diff does this and fixes the problem that I have with creating two CXFServlets. Hopefully this is the right way to do this. Thanks, Gary This is not an offer (or solicitation of an offer) to buy/sell the securities/instruments mentioned or an official confirmation. Morgan Stanley may deal as principal in or own or act as market maker for securities/instruments mentioned or may advise the issuers. This is not research and is not from MS Research but it may refer to a research analyst/research report. Unless indicated, these views are the author's and may differ from those of Morgan Stanley research or others in the Firm. We do not represent this is accurate or complete and we may not update this. Past performance is not indicative of future returns. For additional information, research reports and important disclosures, contact me or see https://secure.ms.com/servlet/cls. You should not use e-mail to request, authorize or effect the purchase or sale of any security or instrument, to send transfer instructions, or to effect any other transactions. We cannot guarantee that any such requests received via e-mail will be processed in a timely manner. This communication is solely for the addressee(s) and may contain confidential information. We do not waive confidentiality by mistransmission. Contact me if you do not wish to receive these communications. In the UK, this communication is directed in the UK to those persons who are professional and eligible counterparties (as defined in the UK Financial Services Authority's rules).