Hi Chris

it's great :-)
that code though may get a bit brittle if other XML-aware providers are 
registered/found.
I do like the idea of updating teh JAXBElementProvider to check the injected 
context for well-known marshaller properties
such that the only thing you do is to

message.put(XML_HEADERS, "<?xml-stylesheet type='text/xsl'> 
href=foobar.xsl'?>");

cheers, Sergey


----- Original Message ----- From: "Chris Marshall" <[email protected]>
To: <[email protected]>
Sent: Tuesday, April 07, 2009 3:55 PM
Subject: Re: How to add Stylesheet to XML returned from server?


Many thanks Sergey, that helped hugely!

Attached is my (skeletal) code which may help other beginners like myself.
Please point out obvious errors.

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.MediaType;

import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
import org.apache.cxf.jaxrs.provider.ProviderFactory;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

public class StylesheetInterceptor extends AbstractPhaseInterceptor<Message>
{

   private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";

   public StylesheetInterceptor() {
       super(Phase.SETUP);
   }

   public void handleMessage(Message message) {

           OperationResourceInfo ori =
message.getExchange().get(OperationResourceInfo.class);

           JAXBElementProvider provider = (JAXBElementProvider)
ProviderFactory
           .getInstance(message)
           .createMessageBodyWriter(
                   ori.getMethodToInvoke().getReturnType(),
                   ori.getMethodToInvoke().getGenericReturnType(),
                   ori.getMethodToInvoke().getAnnotations(),
                   MediaType.APPLICATION_XML_TYPE,
                   message);

           Map<String, Object>properties = new HashMap<String, Object>();
           properties.put(XML_HEADERS, "<?xml-stylesheet type='text/xsl'
href=foobar.xsl'?>");
           provider.setMarshallerProperties(properties);
   }

   public void handleFault(Message message) {
       System.out.println("Stylesheet Error");
   }
}

On 07/04/2009, Sergey Beryozkin <[email protected]> wrote:

Hi,

You can set up a JAXRS endpoint like this :

JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
factory.setResourceClasses(myService.class);
JAXBElementProvider provider = new JAXBElementProvider();
p.setMarshallerProperties(properties);
factory.setProviders(provider);
factory.create();

Actually, another way to do it would be to do something like this in a
custom ResponseHandler filter (or indeed
from your custom CXF out interceptor) :

ProviderFactory.getInstance(message).createMessageBodyWriter(responseClass,
genericType, annotations,
  MediaType.APPLICATION_XML_TYPE, message);

You can get the first 3 parameters for this invocation by doing

message.getExhange().get(OperationResourceInfo.class).getMethodToInvoke()
amd picking them up from a Method instance.

So then you can cast the returned instance to a JAXBElementProvider and set
required properties on it...

Actually, may be we can also enhance the JAXBElementProvider to check the
injected message context for marshaller properties which might've been setup
by cxf interceptors, so the only thing you'd need to do then would be to
just set a marshaller property on a message itself..

Does it really help ?

Cheers, Sergey





Reply via email to