Hi Pedro
> But when you use JSONProvider you have to use "application/json" to
get
"JSON".
Yes, it's hardcoded at the moment
> I know it doesn't right not to use "application/json", but I think
that
should be developer decision.
Actually, I agree with you - whatever fits best the developer's
application is the right decision.
> public final class JSONProvider extends AbstractJAXBProvider { ... }
I'll fix it - I see no reason in it being final - I didn't even know it
was :-)
>@ProduceMime("text/plain" )
>public ContactEntry get() { ... }
>Produces XML because I'm using JAXB. (It isn't good using XML like
plain
Actually, I updated the JAXB provider to produce/consume either
application/xml or text/xml
> <bean id="jsonProvider"
class="org.apache.cxf.jaxrs.provider.JSONProvider"/>
json is supported by default so there's no need to explicitly register
it unless you need to configure a JSON provider or pass it to a
delegation handler as in your case.
Overall you raise an interesting question : how to extend providers to
support arbitrary mime types. I've seen this issue raised at the Jersey
list too.
I reckon we can address this issue similarly to the way you suggested.
We can start with JAXB and JSON ones and update other providers as
needed.
Basically, they can omit static Produces/Consumes definitions (which is
equivalent to using */* as their values) and have a list of mime types
supported by default instead.
So for ex, in case of JSON we'll have
@Provider
public class JSONProvider extends AbstractJAXBProvider {
protected List<MediaType> consumeTypes = ...
protected List<MediaType> produceTypes = ...
// will contain application/json at init
}
And have the setter method which will allow either append to or
overwrite this list from Spring.
Next, in isWriteable, isReadable we will match these values against the
Produces/Consumes on Class/Method
I need to think about it a bit more...
Thanks, Sergey
-----Original Message-----
From: Pedro Ballesteros [mailto:[EMAIL PROTECTED]
Sent: 28 November 2008 19:30
To: [email protected]
Subject: Re: Json and XML @ProduceMime
But I think there is a problem with JSONProvider. Because when you don't
use
it, you can configure whatever Content-type you like in your service
class,
and your body-content could be a different content-type.
But when you use JSONProvider you have to use "application/json" to get
"JSON". If you use another Content-Type, like "text/json" or whatever
you
want, JSONProvider doesn't receive the request and you get XML, not
JSON.
The problem is @ProduceMime and @ConsumeMime in JSONProvider, that you
can't
override with inheritance because it is final class. So, I had to use
Delegation Pattern.
I tell details here:
When you use JSONProvider your services only can work with MIME
"application/json". If you configure another MIME in your service,
JSONProvicer doesn't process the request and doesn't change XML into
JSON.
I know it doesn't right not to use "application/json", but I think that
should be developer decision. Maybe I need to use "plain/text",
"json/text",
even if it's wrong.
The problem is just JSONProvider Produces, Consumes declaration:
@Produces("application/json")
@Consumes("application/json")
@Provider
public final class JSONProvider extends AbstractJAXBProvider { ... }
And you can't override class Annotations because JSONProvider is final.
I think it should be this way:
@Produces("*/*")
@Consumes("*/*")
@Provider
public final class JSONProvider extends AbstractJAXBProvider { ... }
So that developers can choose Produces and Consumers they mean in
Service
Beans.
Ej:
When I don't use JSONProvider the behavior is like this:
@GET
@ProduceMime("text/plain" )
public ContactEntry get() { ... }
Produces XML because I'm using JAXB. (It isn't good using XML like plain
text content type, I know, but I can).
@GET
@ProduceMime("text/xml" )
public ContactEntry get() { ... }
Produces XML too. (That's better).
So I can choose the content type when I don't use JSONProvider, even if
i'm
doing bad things.
But if I use JSONProvider:
<jaxrs:server id="contactsRemoteService" address="/">
<jaxrs:serviceBeans>
<ref bean="contactsService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="jsonProvider"
class="org.apache.cxf.jaxrs.provider.JSONProvider"/>
With:
@GET
@ProduceMime("text/plain" )
public ContactEntry get() { ... }
or
@GET
@ProduceMime("text/json" )
public ContactEntry get() { ... }
My service produces XML, but with:
@GET
@ProduceMime("json/application" )
public ContactEntry get() { ... }
It produces JSON.
Maybe I'd like to configure my service like that, I can't. And as
JSONProvider is a final class, the only solution is delegation pattern:
This code is tested:
// JSON don't decides Content-Type
@ProduceMime("*/*")
@ConsumeMime("*/*")
@Provider
public class FreeMimeJSONProvider extends AbstractJAXBProvider {
private JSONProvider jsonProvider;
public void setJsonProvider(JSONProvider jsonProvider) {
this.jsonProvider = jsonProvider;
}
@Override
public void setSchemas(List<String> locations) {
jsonProvider.setSchemas(locations);
}
public void setNamespaceMap(Map<String, String> namespaceMap) {
jsonProvider.setNamespaceMap(namespaceMap);
}
public Object readFrom(Class type, Type genericType, Annotation[]
annotations, MediaType m,
MultivaluedMap<String, String> headers, InputStream is)
throws IOException {
return jsonProvider.readFrom(type, genericType, annotations, m,
headers, is);
}
public void writeTo(Object obj, Class<?> cls, Type genericType,
Annotation[] anns,
MediaType m, MultivaluedMap<String, Object> headers,
OutputStream
os)
throws IOException {
jsonProvider.writeTo(obj, cls, genericType, anns, m, headers,
os);
}
}
So Content-Types are configured in service classes, as always:
@Path ("/")
public class ContactsService {
@GET
@ProduceMime("text/json" ) // I'm using JSONProvider but I wan't
"text/json" MIME
public ContactEntry get() {
....
}
}
And in Spring:
<jaxrs:server id="contactsRemoteService" address="/">
<jaxrs:serviceBeans>
<ref bean="contactsService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<!-- JSONProvider inside My Provider just to override Consumers
Produces
Annotations -->
<bean id="jsonProvider" class="aa.aaaaa.aaaaa.FreeMimeJSONProvider">
<property name="jsonProvider">
<bean class="org.apache.cxf.jaxrs.provider.JSONProvider"/>
</property>
</bean>
<bean id="contactsService" class="aa.aaaaa.aaaaa.ContactsService" />
Best Regards,
Pedro
Sergey Beryozkin-3 wrote:
>
> Hi Dawa
>
> No problems at all - good news it's all working for you now...
>
> Cheers, Sergey
>
>> Sorry for polluting the Mailing list. I figured out why my problem
was.
>>
>> I had to use
>>
>> @ProduceMime({"application/json", "application/xml"})
>>
>> Now, I am happily switching the response type based on the query
param
>> _type.
>>
>> Dawa :-D
>>
>> On Mon, Nov 17, 2008 at 2:10 PM, Dawa Sherpa <[EMAIL PROTECTED]>
wrote:
>>
>>> Is there a way I can produce both XML and JSON based on the same
method.
>>>
>>> In order for one to use _type=json|xml query param, there needs to
be
>>> two
>>> separate function mounted to a PATH.
>>>
>>>
>>> How can I achieve alternate responses just based on one method ?
>>>
>>>
>>> I tried doing
>>> @ProduceMime("application/json, application/xml") , but still had no
>>> luck.
>>>
>>> Dawa
>>>
>>
>
>
>
--
View this message in context:
http://www.nabble.com/Json-and-XML-%40ProduceMime-tp20549326p20739465.ht
ml
Sent from the cxf-user mailing list archive at Nabble.com.