如何在同一Spring服务中实现多个SFDC出站消息接收器? [英] How to implement multiple SFDC Outbound Message receivers in the same Spring service?
问题描述
对于每条出站消息,Salesforce均提供完整的自包含WSDL.
For each Outbound Message, Salesforce provides a full self-contained WSDL.
使用jaxws-maven-plugin
生成类并使用@Endpoint
,@PayloadRoot
等绑定终结点,为单个服务实现Spring服务很容易.
Implementing a Spring service for a single one is easy, using jaxws-maven-plugin
to generate the classes and @Endpoint
, @PayloadRoot
, etc to bind the endpoint.
但是,对于不同的结构和类型层次结构,多个出站邮件都共享相同的QN(例如http://soap.sforce.com/2005/09/outbound:notifications
或urn:sobject.enterprise.soap.sforce.com:sObject
).
However, multiple Outbound Messages all share the same QNs (for example http://soap.sforce.com/2005/09/outbound:notifications
or urn:sobject.enterprise.soap.sforce.com:sObject
) for different structures and type hierarchies.
我知道如何根据URL路径将相同的XML名称映射到不同的处理程序.
我知道如何对带有绑定文件的生成的类使用单独的包:
I know how to use a separate package for the generated classes with a bindings file:
<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
wsdlLocation="../wsdl/SFDC_Contact_Outbound_Msg.wsdl"
version="2.0">
<jaxb:bindings node="//xs:schema[@targetNamespace='http://soap.sforce.com/2005/09/outbound']">
<jaxb:schemaBindings>
<jaxb:package name="com.sforce.soap.outbound.contact"/>
</jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings node="//xs:schema[@targetNamespace='urn:sobject.enterprise.soap.sforce.com']">
<jaxb:schemaBindings>
<jaxb:package name="com.sforce.soap.enterprise.sobject.contact"/>
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxws:bindings>
但是,当尝试从生成的代码初始化Jaxb2Marshaller
时,它仍然无法处理XML冲突:
However, when trying to initialise the Jaxb2Marshaller
from the generated code, it still cannot handle the XML conflicts:
[WARN] [main] 09:40:45.687 AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'marshaller' defined in class path resource [WebServiceConfig.class]:
Invocation of init method failed; nested exception is org.springframework.oxm.UncategorizedMappingException:
Unknown JAXB exception; nested exception is com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 6 counts of IllegalAnnotationExceptions
Two classes have the same XML type name "{urn:sobject.enterprise.soap.sforce.com}sObject". Use @XmlType.name and @XmlType.namespace to assign different names to them.
...
当SDFC生成的WSDL更改时,除了添加新文件之外,我不想添加任何其他手动步骤.
I do not want to add any more manual steps when the SDFC-generated WSDL changes, other than dropping in the new files.
是否可以在不更改源WSDL的情况下更改package-info.java
中的名称空间?
Is there a way to change the namespaces in package-info.java
without changing the source WSDL?
是否有一种方法可以轻松地(即,没有为每个包装使用单独的@Bean
方法)为每个程序包创建一个单独的编组器,然后将其全部添加到DefaultMethodEndpointAdapter
中?
Is there a way to easily (i.e. not with a separate @Bean
method for each) create a separate marshaller for each package that could all then be added to the DefaultMethodEndpointAdapter
?
是否有另一种方法来实现所有这些出站消息接收器?
Is there another way to implement all these Outbound Message receivers?
推荐答案
是否可以更改名称空间?
Is there a way to change the namespaces?
如果您这样做了,它们将与实际消息中的名称空间不匹配,因此它不会是不可编组的.
If you did they wouldn't match the namespaces in the actuall message, so it wouldn't be unmarshallable.
有没有一种方法可以轻松地为每个程序包创建一个单独的封送处理程序?
Is there a way to easily create a separate marshaller for each package?
好吧,这是一种方法.
@PostConstruct
public void marshallers() throws IOException {
List<String> types = Arrays.stream(applicationContext.getResources("classpath:com/sforce/soap/outbound/*"))
.map(Resource::getFilename)
.collect(Collectors.toList());
for (String type : types) {
String beanName = "marshallingPayloadMethodProcessor_" + type;
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(
"com.sforce.soap.outbound." + type,
"com.sforce.soap.enterprise.sobject." + type
);
try {
marshaller.afterPropertiesSet();
} catch (Exception ex) {
throw new BeanInitializationException("Could not initialize bean " + beanName, ex);
}
MarshallingPayloadMethodProcessor processor = new MarshallingPayloadMethodProcessor(marshaller);
beanFactory.registerSingleton(beanName, processor);
}
对此的警告:
- 如果通过jar进行部署,则classpath目录不存在,因此将需要一种替代方法来获取软件包名称.
-
registerSingleton
似乎破坏了某些应用程序上下文-导致不再找到不相关的bean.我不知道为什么会这样.
- If deploying via a jar, then classpath directories don't exist, so will need an alternate way to get the package names.
registerSingleton
appears to break some application contexts - causing unrelated beans to be no longer be found. I have no idea why this is.
这篇关于如何在同一Spring服务中实现多个SFDC出站消息接收器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!