【问题标题】:schemaLocation ignored when marshalling JAXB Classes using Metro使用 Metro 编组 JAXB 类时忽略 schemaLocation
【发布时间】:2012-10-08 09:22:25
【问题描述】:

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

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

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

另外一点是,在 Java SE 环境中创建 Web 服务客户端和调用 Web 服务时,@UsesJAXBContext、@WebServiceClient 和 @XmlSchema 等某些注解似乎被忽略了。 (我必须在这里声明,我是 Java Web 服务方面的初学者)

【问题讨论】:

    标签: java xml web-services xsd jaxb


    【解决方案1】:

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

    首先,您必须更改 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 上下文实现...

    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) 的阅读,这是到达 marshaller 的唯一方法。

    NOTE2 RI final 类有一个向下转换。这仅适用于参考实现。 YMMV

    【讨论】:

    • 感谢您的回复。但是,您的建议似乎是针对有权访问服务器端的开发人员,即 Web 服务实现。不是这种情况。我只是在创建一个 Web 服务客户端。我拥有的关于 Web 服务的唯一信息是 wsdl 和一个文档,该文档建议将 xsd 文件的模式位置放在传递给 Web 服务端点的 xml 中
    • 那么真正的问题是什么?你不能调用 web 服务,因为你得到什么错误?还是更根本?
    • 这是一个基本的“问题”。我可以调用网络服务,但我没有收到任何警告或错误。只是webservice提供者建议将描述业务数据模式的业务xsd的schemalocation设置到要上传的xml中。我想知道为什么在Java SE环境中使用时没有办法做到这一点JAXB Metro 堆栈 - 即无法访问编组器。
    • Web 服务具有通信所需的所有模式,在 WSDL 中指定,所以我不明白您需要设置什么。由于您没有收到任何错误或警告,因此对 Web 服务的调用正常,对吗?
    • 重新思考整个问题后,我想你是对的。 WSDL 具有到 XSD 的链接,因此无需在 XML 中另外设置 schemaLocation。谢谢!
    猜你喜欢
    • 2011-05-22
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    相关资源
    最近更新 更多