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.html
Sent from the cxf-user mailing list archive at Nabble.com.

Reply via email to