Hello Sergey, well, we are talking about a case, when a client is sending wrong XML to a service. Changing the concept of a service just because of that is way too much I think. Our services look like this:
- CRUD operations for one resource this service is about (schema A) - Retrieve sub-resources of this resource (schema A) - Retrieve virtual resources related to this resource (one schema per virtual resource) - Perform tasks on this resource (one schema per task) - (Special operations) (special schemas) This concept is grown in history so changing all this because of this negative scenario is not very nice. I do not really understand, what is different with the concept of multiple SchemaHandlers. Could you please explain this to me? Best -----Original Message----- From: Sergey Beryozkin [mailto:[email protected]] Sent: Tuesday, September 25, 2012 1:00 PM To: [email protected] Cc: Voß, Marko Subject: Re: UnmarshalException instead of SchemaValidationException After realizing we ship a SchemaHandler utility class (which just groups schema locations and an optional catalogLocation plus a resulting Schema) I proceeded with implementing the suggestion from Dan re method/type-specific input validation, adding a Map<String, SchemaHandler> was all that was needed... Example, when a service wide validation does not work: <bean id="handler1" class="org.apache.cxf.jaxrs.util.SchemaHandler"> <!-- set schemaLocations and, if needed, catalogLocation </bean> <bean id="handler2" class="org.apache.cxf.jaxrs.util.SchemaHandler"> <!-- set schemaLocations and, if needed, catalogLocation </bean> <bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider"> <!-- link class names with individual handlers, using a schemaHandlers map property --> </bean> So if you have A and B classes requiring individual schemas, then use a 'schemaHandlers' property. Ideally, the refactoring (splitting the service into multiple endpoints, etc) is preferred - but I guess that may not be easy in some cases, especially when splitting affects the actual request URI, etc... I have no much time to add more tests at the moment but I have a test where a single SchemaHandler is shared between JAXB and JSON providers, so SchemaHandler itself works, Marko if you can test the snapshots in a day or two then it would be good too Cheers, Sergey On 20/09/12 17:28, Sergey Beryozkin wrote: > a would be ServiceB was wrongly typed, should be > > @Path("/root/b") > public void ServiceB { > @POST > public B postB(B) {} > } > > > Sergey > > On 20/09/12 17:26, Sergey Beryozkin wrote: >> On 20/09/12 17:11, Daniel Kulp wrote: >>> >>> On Sep 20, 2012, at 12:04 PM, "Voß, >>> Marko"<[email protected]> wrote: >>> >>>> I'll talk to the team tomorrow. Maybe the new behavior is >>>> acceptable but I doubt that. >>> >>> CXF just keeps a javax.xml.validation.Schema object around that >>> represents the schema for the entire service. We pass that into JAXB. >>> We don't have the ability to have a separate Schema object per >>> operation at this time. I'd be open for a patch for this, but quite >>> honestly, I'm not sure how the configuration for that would look. >>> You would need a way to configure a unique schema for each >>> operation/type which would result in a bunch of .xsd files, etc. >>> >> Indeed. May be one more option, if that is possible, to split the >> original endpoint into two ones, say if we have >> >> @Path("/root") >> public void Service { >> @Path("/a") >> @POST >> public A postA(A) {} >> >> @Path("/b") >> @POST >> public B postA(B) {} >> } >> >> then it can be split into two endpoints. with each of them - having >> unique schemas: >> >> >> @Path("/root/a") >> public void ServiceA { >> @POST >> public A postA(A) {} >> } >> >> >> @Path("/root/b") >> public void ServiceB { >> @Path("/b") >> @POST >> public B postA(B) {} >> } >> >> Cheers, Sergey >> >> >>> >>> Dan >>> >>> >>>> >>>> >>>> Best, >>>> >>>> -----Original Message----- >>>> From: Sergey Beryozkin [mailto:[email protected]] >>>> Sent: Thursday, September 20, 2012 5:26 PM >>>> To: Voß, Marko >>>> Cc: [email protected] >>>> Subject: Re: UnmarshalException instead of >>>> SchemaValidationException >>>> >>>> One more thing, after seeing a response from Dan in the other >>>> thread, >>>> >>>> Unmarshaller.Listener can also be registered with the provider, not >>>> sure it can help in your case, but mentioning it just in case >>>> >>>> Sergey >>>> On 20/09/12 16:06, Sergey Beryozkin wrote: >>>>> On 20/09/12 15:48, Sergey Beryozkin wrote: >>>>>> On 20/09/12 15:39, Voß, Marko wrote: >>>>>>>> I guess I'm not understanding the problem well. You said earlier: >>>>>>> >>>>>>>>>> In a negative test, I send some XML to this service, which is >>>>>>>>>> wrong XML for type A. Let's say the XML is of type B. The XML >>>>>>>>>> passes the schema validation, because of it is valid for type B". >>>>>>> >>>>>>>> AFAIK, at the schema validation level, all JAXB does is ensures >>>>>>>> the incoming XML is valid according to the schema, which it is >>>>>>>> according to what you said earlier on. >>>>>>> >>>>>>> In the old code of this service, the service validated the >>>>>>> incoming XML against the schema of the expected type. >>>>>>> In the example, the XML got validated against the schema of type >>>>>>> A, no matter what XML was incoming. I expected the same behavior >>>>>>> with CXF, since I define the expected type in the signature. >>>>>>> >>>>>>>> Unmarshalling is at the next stage, so if the previous stage >>>>>>>> let 'B' >>>>>>>> to come in then obviously the unmarshaller expecting it to be 'A' >>>>>>>> throws UnmarshallException. I do not see how to make >>>>>>>> SchemaValidationException thrown if the schema validation phase >>>>>>>> passes... >>>>>>> >>>>>>> I meant, that the schema validation phase should not pass, >>>>>>> because the wrong schema is being used right now. >>>>>> >>>>>> Well, you have a schema document which is registered with the >>>>>> JAXB provider so this is what is used to validate the incoming XML. >>>>>> >>>>>> >>>>>>> It should use the schema of the type defined in the signature >>>>>>> and not the schema, which fits to the incoming XML. >>>>>> >>>>>> Is it possible in JAXB to configure Unmrashaller such that it >>>>>> validates the incoming XML based on the information it obtains >>>>>> while populating A, some kind of Java-based in validation ? >>>>>> >>>>>> If yes we can do that >>>>> >>>>> In fact this can probably be enforced at the custom >>>>> XMLStreamReader level. >>>>> What about this: >>>>> - register custom RequestHandler filter >>>>> - at that level we know the matching Method >>>>> - know, register the basic XMLStreamReader on the current message >>>>> (extending the CXF helper reader), initialized with the info >>>>> obtained from the Method or say from XmlType annotation on the relevant >>>>> class). >>>>> If the root XML name is not matching the expectations - throw the >>>>> schema validation exception... >>>>> >>>>> Not sure if it is something that will do in your case, but >>>>> technically it can be easily done, can provide more info if needed... >>>>> >>>>> Cheers, Sergey >>>>> >>>>> >>>>> >>>>>> >>>>>> Cheers, Sergey >>>>>> >>>>>> >>>>>>> >>>>>>> -----Original Message----- >>>>>>> From: Sergey Beryozkin [mailto:[email protected]] >>>>>>> Sent: Thursday, September 20, 2012 4:21 PM >>>>>>> To: Voß, Marko >>>>>>> Cc: [email protected] >>>>>>> Subject: Re: UnmarshalException instead of >>>>>>> SchemaValidationException >>>>>>> >>>>>>> On 20/09/12 14:08, Voß, Marko wrote: >>>>>>>> Hello, >>>>>>>> >>>>>>>>> I guess if a schema is open enough to accept either A or B >>>>>>>>> representations, then there's no bug. >>>>>>>> >>>>>>>> That is not the case here. >>>>>>>> >>>>>>> >>>>>>> I guess I'm not understanding the problem well. You said earlier: >>>>>>> >>>>>>>>> In a negative test, I send some XML to this service, which is >>>>>>>>> wrong >>>>>>> XML for type A. Let's say the XML is of type B. The XML passes >>>>>>> the schema validation, because of it is valid for type B". >>>>>>> >>>>>>> AFAIK, at the schema validation level, all JAXB does is ensures >>>>>>> the incoming XML is valid according to the schema, which it is >>>>>>> according to what you said earlier on. >>>>>>> >>>>>>> Unmarshalling is at the next stage, so if the previous stage let 'B' >>>>>>> to come in then obviously the unmarshaller expecting it to be 'A' >>>>>>> throws UnmarshallException. I do not see how to make >>>>>>> SchemaValidationException thrown if the schema validation phase >>>>>>> passes... >>>>>>> >>>>>>>>> I can see that Unmarshaller can also accept >>>>>>>>> ValidationEventHandler ("validationHandler" provider >>>>>>>>> property). Not sure if it can help - may be you can restrict it there >>>>>>>>> somehow. >>>>>>>> >>>>>>>> Well, we are using the schema validation setup this way already: >>>>>>>> >>>>>>>> <bean name"myJaxbProvider" class="..."> <property >>>>>>>> name="catalogLocation" value="..."/> <property >>>>>>>> name="schemaLocations" value="..."> <list> >>>>>>>> <value>classpath:/xsd/foo.xsd</value> >>>>>>>> ... >>>>>>>> </list> >>>>>>>> </property> >>>>>>>> </bean> >>>>>>>> >>>>>>>> So we have to setup the validation twice or remove this kind of >>>>>>>> validation, we have been talking about lately, and use the >>>>>>>> validationHandler instead? >>>>>>>> >>>>>>> I think ValidationEventHandler is there to complement the >>>>>>> validation set up, for the handler to get more info about the >>>>>>> validation process >>>>>>> >>>>>>>>> May my using JAXBElement<A> instead of A is more restrictive, >>>>>>>>> can you try it ? >>>>>>>> >>>>>>>> Tested this with no difference in the result. >>>>>>>> >>>>>>> OK... >>>>>>> >>>>>>> Cheers, Sergey >>>>>>>> >>>>>>>> Best, >>>>>>>> >>>>>>>> -----Original Message----- >>>>>>>> From: Sergey Beryozkin [mailto:[email protected]] >>>>>>>> Sent: Thursday, September 20, 2012 2:27 PM >>>>>>>> To: [email protected] >>>>>>>> Cc: Voß, Marko >>>>>>>> Subject: Re: UnmarshalException instead of >>>>>>>> SchemaValidationException >>>>>>>> >>>>>>>> Hi >>>>>>>> On 20/09/12 13:02, Voß, Marko wrote: >>>>>>>>> Hello, >>>>>>>>> >>>>>>>>> Say, we have a JAX-RS method like this: >>>>>>>>> >>>>>>>>> @PUT >>>>>>>>> @Path("/foo") >>>>>>>>> @Produces(MediaType.TEXT_XML) >>>>>>>>> @Consumes(MediaType.TEXT_XML) >>>>>>>>> public static A create(A a); >>>>>>>>> >>>>>>>>> In a negative test, I send some XML to this service, which is >>>>>>>>> wrong XML for type A. Let's say the XML is of type B. The XML >>>>>>>>> passes the schema validation, because of it is valid for type >>>>>>>>> B but this method expects type A and so we get a >>>>>>>>> UnmarshalException instead of the SchemaValidationException >>>>>>>>> complaining about the wrong element found. >>>>>>>>> >>>>>>>>> Is it a bug, that the schema validation is not using the >>>>>>>>> schema for type A? It looks like it is using the schema, which >>>>>>>>> is responsible for the root element of the passed XML if found. >>>>>>>>> >>>>>>>> >>>>>>>> I guess if a schema is open enough to accept either A or B >>>>>>>> representations, then there's no bug. >>>>>>>> >>>>>>>> I can see that Unmarshaller can also accept >>>>>>>> ValidationEventHandler ("validationHandler" provider property). >>>>>>>> Not sure if it can help - may be you can restrict it there somehow. >>>>>>>> >>>>>>>> May my using JAXBElement<A> instead of A is more restrictive, >>>>>>>> can you try it ? >>>>>>>> >>>>>>>> Cheers, Sergey >>>>>>>> >>>>>>>>> best, >>>>>>>>> >>>>>>>>> >>>>>>>>> ------------------------------------------------------- >>>>>>>>> >>>>>>>>> Fachinformationszentrum Karlsruhe, Gesellschaft für >>>>>>>>> wissenschaftlich-technische Information mbH. >>>>>>>>> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht >>>>>>>>> Mannheim HRB 101892. >>>>>>>>> Geschäftsführerin: Sabine Brünger-Weilandt. >>>>>>>>> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner. >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> ------------------------------------------------------- >>>>>>>> >>>>>>>> Fachinformationszentrum Karlsruhe, Gesellschaft für >>>>>>>> wissenschaftlich-technische Information mbH. >>>>>>>> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht >>>>>>>> Mannheim HRB 101892. >>>>>>>> Geschäftsführerin: Sabine Brünger-Weilandt. >>>>>>>> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner. >>>>>>>> >>>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> ------------------------------------------------------- >>>>>>> >>>>>>> Fachinformationszentrum Karlsruhe, Gesellschaft für >>>>>>> wissenschaftlich-technische Information mbH. >>>>>>> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht >>>>>>> Mannheim HRB 101892. >>>>>>> Geschäftsführerin: Sabine Brünger-Weilandt. >>>>>>> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner. >>>>>>> >>>>>>> >>>>> >>>>> >>>> >>>> >>>> >>>> >>>> ------------------------------------------------------- >>>> >>>> Fachinformationszentrum Karlsruhe, Gesellschaft für >>>> wissenschaftlich-technische Information mbH. >>>> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht >>>> Mannheim HRB 101892. >>>> Geschäftsführerin: Sabine Brünger-Weilandt. >>>> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner. >>>> >>>> >>> >> ------------------------------------------------------- Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. Geschäftsführerin: Sabine Brünger-Weilandt. Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
