使用Metro编组JAXB类时忽略schemaLocation

时间:2012-10-08 09:22:25

标签: java xml web-services xsd jaxb

我正在使用捆绑了Java 6 SE的Metro堆栈来调用Web服务。 Web服务期望XML作为参数。我使用JAXB类来创建内容并将我的JAXB根元素传递给Web服务端点。

现在我的问题:我找不到任何方法使marshaller包含XSD文件的schemaLocation,因为我无法直接访问marshaller。 (如果您可以直接访问marshaller,可以将schemalocation设置为属性,但在使用metro时,所有编组操作似乎都在内部进行。)

我已尝试在生成的package-info.java类的XmlSchema注释中设置xsi:schemaLocation,但这对生成的xml没有影响。

另一点是,在Java SE环境中创建Web服务客户端并调用Web服务时,某些注释(如@UsesJAXBContext,@ WebServiceClient和@XmlSchema)似乎会被忽略。 (我必须在此声明我是Java Web服务的初学者)

1 个答案:

答案 0 :(得分:2)

好的,这就是我现在所知道的。几个月来,这对我来说一直是个问题。

首先,您必须更改JAX-WS使用的JAXBContext。为此,请在服务器上使用@UsesJAXBContext注释。 (com.sun.xml.ws.developer.UsesJAXBContext)

然后,在您的工厂实现中,您必须使用此方法返回自定义桥。

public Bridge createBridge(final TypeReference typereference)

然后您的自定义网桥需要设置marshaller属性以设置您要使用的命名空间映射器。

这是我的例子。

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

和工厂类......

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);
    }
}

和JAXB Context forlelelement ......

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));
}

现在是Bridge实施......

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);
}

注意:我刚刚包装了现有的实现。我想要的就是能够修复命名空间名称。从我阅读源代码(JAXWS),这是到达编组人员的唯一方法。

NOTE2 RI最终课程有一个向下倾斜。这仅适用于参考实现。 YMMV