问题
In my application, I am consuming a third party web-service that is provided by my client.
I have developed my application on Spring and Hibernate framework and in one module I am consuming this third party web-service url. I have generated web-service stubs using
javab2-maven-plugin
The maven plugin in declared as below in my pom.xml file :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Package to store the generated file -->
<packageName>com.equifax.unsolicited.wsdl.stub</packageName>
<!-- Treat the input as WSDL -->
<wsdl>true</wsdl>
<!-- Input is not XML schema -->
<xmlschema>false</xmlschema>
<!-- The WSDL file that you saved earlier -->
<schemaFiles>Duk_CIS_Send_CreditStatus.wsdl</schemaFiles>
<!-- The location of the WSDL file -->
<schemaDirectory>${project.basedir}/src/main/wsdl</schemaDirectory>
<!-- The output directory to store the generated Java files -->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!-- Don't clear output directory on each run -->
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
And I am using the auto-generated JAXB java classes to call the web service. I have created a service bean which call the web service :
@Service("unsolicitResponseService")
public class UnsolicitResponseServiceImpl implements UnsolicitResponseService{
private static final Logger LOGGER = Logger.getLogger(UnsolicitResponseServiceImpl.class);
@Autowired
private WebServiceTemplate webServiceTemplate;
@Override
public void sendUnsolicitResponse() {
LOGGER.debug("Calling Duke Web Service to Send Unsolicit Response ... ");
try{
ObjectFactory objecFactory = new ObjectFactory();
CreditStatusMsgType creditStatusMessage = objecFactory.createCreditStatusMsgType();
creditStatusMessage.setMessageHeader(createMessageHeader(objecFactory));
//WRAP THE CLASS AS THE INSTANCE OF JAXBELEMENT OTHERWISE IT WILL THROW MISSING ROOTELEMENT ERROR
JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement = objecFactory.createSendCreditStatus(creditStatusMessage);
//CREATE STRING WRITER TO LOG THE REQUEST
Object response = this.webServiceTemplate.marshalSendAndReceive(creditStatusMessageJaxbElement);
LOGGER.debug("Jumio Web Service Response Reponse :"+response);
LOGGER.debug("Unsolicit Response sent to Duke Successfully.");
}catch(Exception ex){
LOGGER.error("Exception generated while calling Web Service to send unsolicit Response : "+ex.getLocalizedMessage(),ex);
}
}
Below is the xml configuration where I have declared interceptors to log the request and response :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- DEFINE SOAP VERSION USED BY A WSDL -->
<bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<!-- FOR TEXT/XML -->
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/>
</property>
</bean>
<!-- LOCATION OF THE GENERATED JAVA FILEs -->
<oxm:jaxb2-marshaller id="marshaller" contextPath="com.equifax.unsolicited.wsdl.stub"/>
<!-- CONFIGURE THE SPRING WEB SERVICE -->
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
<property name="defaultUri" value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/>
</bean>
<sws:interceptors>
<bean id="jumioPeyLoadLoggingInterceptor" class="com.test.datasource.logging.interceptor.PayloadLoggingInterceptor">
</bean>
<bean id="jumioSOAPLoggingInterceptor" class="com.test.datasource.logging.interceptor.SOAPLoggingInterceptor">
</bean>
</sws:interceptors>
</beans>
And I also have added and new logging category to enable the logger level to DEBUG mode :
Above code is calling the web service successfully. But the interceptors are not getting called. So I am not able to log the XML request and response.
Here, I am assuming that, these interceptors will not work while consuming the service. Let me know if I am wrong here.
I am referring Spring Web Service from HERE . This website has given explanation interceptors while publishing a web-service.
Kindly let me know should we use this interceptors while consuming a web-service ? Or How should I print request and response which are JAXB-ELEMENT ?
回答1:
I am adding here solution which I have implemented. There are two ways by which we can implement this solution. I have implemented the second one from below list using JAXBContext and Marshaller.
1> Log Request/Response By interceptor.
We can not use PayloadLoggingInterceptor or SOAPLoggingInterceptor when we are consuming the web service.
We need to use ClientInterceptor when we are consuming the web service. ClientInterceptor is implemented by PayloadValidatingInterceptor class which is used to intercept the request/response and validate the it based on xsd schema.
For that we need to provide interceptor reference as below :
<bean id="MyPayloadValidatingInterceptor" class="com.equifax.ic.datasource.jumio.ws.logging.interceptor.JumioPayloadValidatingInterceptor">
<property name="schema" value="file:WebContent/WEB-INF/schemas/account-balance-service.xsd" />
<property name="validateRequest" value="false" />
<property name="validateResponse" value="false" />
</bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
<property name="defaultUri" value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/>
<property name="interceptors">
<list>
<ref bean="MyPayloadValidatingInterceptor"/>
</list>
</property>
</bean>
2> Log Request/Response by using JAXBContext
This is the solution which I have implemented in my application as we should not use PayloadValidatingInterceptor only to log reqeust/response.
private void logJAXBRequest(JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement){
LOGGER.debug("Logging Web Service Request ...");
StringWriter writer = null;
StreamResult streamResult = null;
StringBuffer buffer = null;
try{
writer = new StringWriter();
streamResult = new StreamResult(writer);
JAXBContext jaxbContext = JAXBContext.newInstance(CreditStatusMsgType.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(creditStatusMessageJaxbElement, streamResult);
buffer = writer.getBuffer();
LOGGER.debug("JAXB Webservice Request : "+ buffer.toString());
writer.close();
}catch(Exception ex){
LOGGER.error("Exception generated while creating XML Logs of JAXB Request :",ex);
}
}
回答2:
He everyone, colleagues. There are two main ways to show XML requests / responses:
First of all you have to add
log4j
dependency into yourpom.xml
file:<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
Then you have to place
log4j.properties
file into a classpath of your application. When I develop SOAP services I often use Spring WS Maven artefact. Unfortunately, a usualresources
folder is not created from scratch and you have to create it manually. Then you placelog4j.properties
file there. The contents of log4j config depends on the approach you want to use (see items below). Obtained structure is following:Use a standard Message Logging and Tracing approach &
log4j.properties
file. Nothing should be configured, developed, written except log4j config file contents. The contents of log4j config should be the following (use these contents as is):log4j.rootCategory=DEBUG, stdout log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%p [%c{3}] %m%n
Use a
PayloadLoggingInterceptor
&log4j.properties
file. Some config changes should be applied, but this approach is more flexible, as for me. First of all you have to addPayloadLoggingInterceptor
into aMessageDispatcherServlet
config file:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:sws="http://www.springframework.org/schema/web-services" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.ln.springws"/> <sws:annotation-driven/> <sws:interceptors> <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" /> </sws:interceptors> <sws:dynamic-wsdl id="holiday" portTypeName="HumanResource" locationUri="http://localhost:8080/holidayService/" targetNamespace="http://spring-ws-holidays.com/hr/definitions"> <sws:xsd location="/WEB-INF/hr.xsd"/> </sws:dynamic-wsdl> </beans>
And at last place the following contents to
log4j.properties
file:log4j.rootLogger=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%-5p [%c] - <%m>%n
And as a result of both approaches you will have something like that in a console:
来源:https://stackoverflow.com/questions/32006048/how-to-use-payloadlogginginterceptor-and-soaplogginginterceptor-interceptors-whi