我需要为每个客户部署相同的网络服务。这@javax.jws.WebService
使用 Object
作为方法参数和返回类型(导致 wsdl 中的 <xs:anyType/>
)。 Web 服务的每个实例都与客户的 jar 一起部署在类路径上。此 jar 具有已知结构并包含客户希望通过我的服务处理的 JAXB 注释类。
问题是,当客户将他的类的实例作为方法 agrument 传递时,服务器端 JAXB 上下文将其解码到一些奇怪的 xerces dom 节点中,因为(据我所知)仅在部署期间 @WebMethod
和 @WebService
扫描了注释,如前所述,所有注释都处理 Object
仅。
简单来说,我需要在 WEB-INF/lib/customer_classes_14586.jar
提示 JAXB这意味着对 JAXBContext
进行一些控制在 JAX-WS 部署期间创建。
有可能吗?
特定于服务器的解决方案很好(带有 metro ws 堆栈的 glassfish 3.1)
更新
我错过了一件可能很重要的事情:我在运行时通过 Web 管理控制台将这些 Web 服务部署为 OSGI 包。当我按下部署按钮时,新的 jar 以编程方式从客户库、web 服务类、wsdl 和 list 构建。因此,如果有帮助,我可以在此时干预构建过程并提供提示信息。
最佳答案
第一个选项是 @UsesJAXBContext
注释。更多信息在这里:Specify JAXB Packages in SLSB and JAX-WS
我还没有测试它,因为当我发现这个注释时,我已经在其他可能对其他人有帮助的解决方案中途了。
关键是使用@WebServiceProvider
而不是@WebService
,有点底层但很简单:
@WebServiceProvider(
wsdlLocation = "WEB-INF/wsdl/injector.wsdl"
)
@ServiceMode(value = Service.Mode.PAYLOAD)
public class InjectorService implements Provider<Source> {
private Unmarshaller unmarshaller;
@Override
public Source invoke(Source request) {
try {
DOMResult requestDom = new DOMResult();
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(request, requestDom);
Node requestNode = requestDom.getNode();
// Get the operation name node.
Node operationNode = requestNode.getFirstChild();
// Get the parameter node.
Node parameterNode = operationNode.getFirstChild();
// Unmarshal
JAXBElement<Object> element = unmarshaller.unmarshal(parameterNode, Object.class);
Object unmarshalled = element.getValue();
// Handling customer object and response ......
} catch (Exception e) {
throw new RuntimeException("Endpoint error", e);
}
}
protected Class[] getCustomerClasses() {
// return customer classes somehow
}
@PostConstruct
public void init() throws Exception {
JAXBContext jbc = JAXBContext.newInstance(getCustomerClasses());
unmarshaller = jbc.createUnmarshaller();
}
}
就是这样。客户类可以从类路径、包上下文或其他任何地方获得。
关于java - 如何在 JAX-WS 中控制 JAXBContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7302549/