That does the trick! Thanks a bunch Dan. --Whaley
On Fri, Jun 10, 2011 at 9:48 AM, Daniel Kulp <[email protected]> wrote: > > > An interceptor would definitely work. In the USER_LOGICAL phase (I > think), > you should be able to do: > > List<Object> list = msg.getContent(List.class); > for (int x = 0; x < list.size(); x++) { > Object o = list.get(x); > if (o instanceof List) { > list.set(x, Collections.unmodifiableList((List)o)): > } > } > > That should work for you case. > > Dan > > > > On Friday, June 10, 2011 11:43:15 AM Jason Whaley wrote: > > Is there a way to make this generally applicable to every single method > > that would return a List<JaxbType>. What I've gathered so far is that > > using a ResponseWrapper means: > > > > 1) The bean used as the class for @ResponseWrapper has to have a property > > that matches the @WebResult name exactly. > > 2) If I try to wildcard the List I use a property in the bean for > > @ResponseWrapper (so that the same bean can be used across all > @WebMethods > > that return a List) I'm back to have a complexType of <xs:sequence> > > containing types of xs:anyType again. > > > > This doesn't look like it will help with the requirements we're trying to > > impose, unfortunately (unless I'm going about using @ResponseWrapper > > incorrectly). > > > > Going back to my original assumption - if I wanted this to be generally > > applicable to every @WebMethod, would a CXF interceptor be useful for > this? > > I'd for us to avoid having to have a single XmlAdapter or bean class for > > @ResponseWrapper for every @WebMethod that returns a List/Collection. > > > > --Whaley > > > > On Wed, Jun 8, 2011 at 10:15 AM, Daniel Kulp <[email protected]> wrote: > > > On Wednesday, June 08, 2011 11:22:08 AM Jason Whaley wrote: > > > > The problem itself manifests where a @WebMethod is actually > specifying > > > > List<SomeJaxbBean> as the return type. As a simple example: > > > > > > > > @WebMethod(operationName = "getRoles") > > > > @WebResult(name = "roles") > > > > List<Role> getRoles( @WebParam(name="roleIds") List<String> roleIds > ); > > > > > > > > Would we be better off just wrapping that list in a specific class > > > > used only as a return type (much like how I suspect wsdl2java would > > > > generate it if you assume your wsdl had an output message that > > > > returned a complexType containing a sequence)? > > > > > > Ah. Right. For this case, you should likely create a wrapper class > for > > > the > > > response and use the @ResponseWrapper annotation to point to it. > The > > > "java2ws" tool has a flag to generate stubs for those if you need it, > but > > > it > > > really would just be another JAXB annotated bean with your list as a > > > property. > > > If you have the @ResponseWrapper pointing to a valid class, CXF will > use > > > it so > > > you should be able to use all the same JAXB things like the > > > afterUnmarshal and > > > such with it. > > > > > > Dan > > > > > > > On Tue, Jun 7, 2011 at 1:46 PM, Daniel Kulp <[email protected]> > wrote: > > > > > My gut feeling is that the best option is to construct the JAXB > bean > > > > > > like > > > > > > > > normal: > > > > > > > > > > public class MyFoo { > > > > > > > > > > List<Blah> blahs = new ArrayList<Blah>(); > > > > > > > > > > ... all the normal things .... > > > > > > > > > > } > > > > > > > > > > > > > > > but then add a method like: > > > > > > > > > > publi void afterUnmarshal(Unmarshaller, Object parent) { > > > > > > > > > > blahs = Collections.unmodifiableList(blahs); > > > > > > > > > > } > > > > > > > > > > to reset it to an unmodifiable collection after the unmarshalling > is > > > > > > > > done. The call to the afterUnmarshal method is part of the spec: > > > > http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller. > > > > > > > > html#unmarshalEventCallback > > > > > > > > > > > > > > > Dan > > > > > > > > > > On Tuesday, June 07, 2011 12:22:50 PM Jason Whaley wrote: > > > > >> (bear with me, this is a bit of a long question) > > > > >> > > > > >> I'm working on a project, Kuali Rice (http://www.kuali.org/rice), > > > > > > that > > > > > > > >> basically acts as a service bus for a series of other systems. We > > > > >> are using CXF behind the scenes to publish JAX-WS annotated > > > > >> services that are written code-first. These services can either > be > > > > >> looked up and accessed by a client through a JAX-WS service proxy > > > > >> or, if Rice is running embedded in an app, an actual reference to > > > > >> the implementation can be given the to client. > > > > >> > > > > >> This works great in the general case. However we've recently > > > > >> started trying to enforce immutability on lots of our model > objects > > > > >> and Collections/Maps of those model objects for various reasons. > > > > >> Our services are using these immutable model objects as both > > > > >> parameters and return types. Where this breaks down with JAX-WS > > > > >> and SOAP is in the case where a service method returns a > Collection > > > > >> of these model objects back and we want the Collection itself to > be > > > > >> immutable (e.g. the type you would get back from one of the > > > > >> Collections.unmodifiable*() methods). If a client makes a service > > > > >> call through the JAX-WS proxy and the return type is > > > > >> List<SomeModelObject> then what it gets back is a modifiable List. > > > > >> This basically means that the two possible implementations that a > > > > >> client can reference will have different behaviors that break the > > > > >> documented expectation of what gets returned from method calls > that > > > > >> return a List type (that expectation being an immutable list). > > > > >> > > > > >> Despite the fact that these services are code first, we are > striving > > > > >> to to make sure that the generated WSDL/XSD from our JAXB and > JAX-WS > > > > >> annotated types and services produce somewhat of a sane contract > for > > > > >> possibly non-java clients to use in the future. As such, doing > > > > >> something like introducing an actual type for an ImmutableList (or > > > > >> using something like ImmutableList from guava) would create > needless > > > > >> and java specific types in the generated WSDL/XSD. We didn't go > > > > >> that route for that very reason. > > > > >> > > > > >> The first thing I tried was to write a simple XmlAdapter to that > > > > >> would return an immutable List reference during unmarshalling. It > > > > >> ended up looking like this: > > > > >> > > > > >> > > > > >> public class ImmutableListAdapter extends XmlAdapter<Object[], > > > > > > List<?>> > > > > > > > >> { > > > > >> > > > > >> @Override > > > > >> public List<?> unmarshal(Object[] objects) throws Exception { > > > > >> > > > > >> return > Collections.unmodifiableList(Arrays.asList(objects)); > > > > >> > > > > >> } > > > > >> > > > > >> @Override > > > > >> public Object[] marshal(List<?> objects) throws Exception { > > > > >> > > > > >> return objects.toArray(); > > > > >> > > > > >> } > > > > >> > > > > >> } > > > > >> > > > > >> > > > > >> This works, but now the generated XSD/WSDL has those sequences > that > > > > >> represent Lists as a sequence of <xs:any> types, which again we'd > > > > >> prefer not to have in order to keep the XSD/WSDL sane in the > future > > > > >> for non java clients to use. We could write an adapter for every > > > > >> single List<SomeModelObject> there such that the unbounded > wildcard > > > > >> type isn't used and we are marshing to/from a > > > > >> SomeJaxbAnnotatedModelObject[] instead of Object[] each time (thus > > > > >> preventing the sequences of xs:any), but this seems like massive > > > > >> overkill to do for every single model object that we have. Is > > > > >> there another possible way to do this with a XmlAdapter that > > > > >> wouldn't require such duplication? > > > > >> > > > > >> If a JAXB Adapter is not the way to go with this, would it > possible > > > > >> (and straightforward) to do this in a CXF interceptor that might > do > > > > >> the same thing as this XmlAdapter but in such a way that it does > not > > > > >> alter the generated XSD? If so, what phase should that > interceptor > > > > >> be bound to? > > > > > > > > > > -- > > > > > Daniel Kulp > > > > > [email protected] > > > > > http://dankulp.com/blog > > > > > Talend - http://www.talend.com > > > > > > -- > > > Daniel Kulp > > > [email protected] > > > http://dankulp.com/blog > > > Talend - http://www.talend.com > > -- > Daniel Kulp > [email protected] > http://dankulp.com/blog > Talend - http://www.talend.com >
