schemaLocation ignored when marshalling JAXB Classes using Metro

情到浓时终转凉″ 提交于 2019-12-24 09:59:58

问题


I'm using the Metro stack bundled with Java 6 SE to call a web service. The web service expects XML as a parameter. I use JAXB classes to create content and pass my JAXB root element to the web service endpoint.

Now to my Problem: I can't find any way to make the marshaller include the schemaLocation of the XSD file since I can't directly access the marshaller. (If you have direct access to the marshaller it is possible do set the schemalocation as a property, but when using metro, all the marshalling seems to be happening internally.)

I've tried setting the xsi:schemaLocation in the XmlSchema annotation in the generated package-info.java class, but this had no effect on the xml generated.

Another point is that when creating a web service client and calling a web service in an Java SE environment, certain annotations like @UsesJAXBContext, @WebServiceClient and @XmlSchema seem to be ignored. (I must state here that I am a beginner in terms of Java web services)


回答1:


Ok, here's what I now know. This has been a problem for me for months.

First, you have to change the JAXBContext used by JAX-WS. To do this use the @UsesJAXBContext annotation on the server. (com.sun.xml.ws.developer.UsesJAXBContext)

Then, in your factory implementation, you have to return custom Bridges in this method.

public Bridge createBridge(final TypeReference typereference)

Then your custom bridge needs to set the marshaller property to set the namespace mapper you want to use.

Here's my example.

@WebService(serviceName = ...)
@UsesJAXBContext(MyContextFactory.class)
public class SoapServer { ... }

and the factory class ...

public static class MyContextFactory implements JAXBContextFactory
{
    @Override
    public JAXBRIContext createJAXBContext(final SEIModel sei,
            @SuppressWarnings("rawtypes") final List<Class> classesToBind, final List<TypeReference> typeReferences)
            throws JAXBException
    {
        JAXBRIContext context = JAXBContextFactory.DEFAULT.createJAXBContext(sei, classesToBind, typeReferences);
        return new MyJaxwsContext(context);
    }
}

and the JAXB Context impelementation...

public class MyContext extends JAXBRIContext
{
/** the actual context */
private final JAXBRIContext delegate;

public MyContext(final JAXBRIContext createContext)
{
    this.delegate = createContext;
}

public Bridge createBridge(final TypeReference arg0)
{
    return new MyBridge((JAXBContextImpl) delegate, delegate.createBridge(arg0));
}

and now the Bridge implementation...

public class MyBridge extends Bridge
{
private final Bridge delegate;

protected MyBridge(final JAXBContextImpl context, final Bridge delegate)
{
    super(context);
    this.delegate = delegate;
}

// an example marshal call. There are many more...
public void marshal(final Marshaller m, final Object object, final ContentHandler contentHandler)
        throws JAXBException
{
    m.setProperty("com.sun.xml.bind.namespacePrefixMapper", namespaceMapper);
    delegate.marshal(m, object, contentHandler);
}

NOTE: I have just wrapped the existing implementation. All I wanted was to be able to fix the namespace names. From my reading of the source (JAXWS), this is the only way to get to the marshaller.

NOTE2 There is a downcast to an RI final class. This only works with the reference implementation. YMMV



来源:https://stackoverflow.com/questions/12778748/schemalocation-ignored-when-marshalling-jaxb-classes-using-metro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!