问题
I am developing a webservice using spring soap implementation and hence my service class is annotated with @Endpoint annotation. Now, I want to use SPRING AOP for application logging which I have already implemented. However, as I have noticed, until I execlude my service class from the pointcut expression, I get no endpoint mapping found exception when my webservice is invoked. When I exclude the service classes from AOP's scope, things work fine again. Any idea on this?
UPDATE:
My logger class
package com.cps.arch.logging;
@Component
@Aspect
public class LoggerAspect {
private static final Logger logger = LoggerFactory.getLogger("Centralized Payment System");
@Before("(execution(* com.cps..*.*(..)) and not execution(* com.cps.service..*.*(..)))")
public void logBefore(JoinPoint joinPoint) {
logger.info("Execution Start : "+"Class: "+joinPoint.getTarget().getClass().getName()+
"Method: "+joinPoint.getSignature().getName());
}
}
My Service Endpoint:
package com.cps.service.impl;
@Endpoint
public class EndpointIntegrationServiceImpl implements EndpointIntegrationService
{
private static final String NAMESPACE_URI = "http://www.example.com/cps/model";
@Autowired
public MYBO myBO ;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "SaveDataRequest")
public void saveData(@RequestPayload
SaveDataRequest data) {
//business layer invocation
}
}
My WS Configuration
@EnableWs
@Configuration
@ComponentScan(basePackages={"com.cps"})
public class WebServiceConfig extends WsConfigurerAdapter
{
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "MyWsdl")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("MyPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://www.example.com/micro/payment/PaymentManagement");
wsdl11Definition.setSchema(reconciliationSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema schema() {
return new SimpleXsdSchema(new ClassPathResource("XSD/MySchema.xsd"));
}
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(validationInterceptor());
}
@Bean
ValidationInterceptor validationInterceptor() {
final ValidationInterceptor payloadValidatingInterceptor = new ValidationInterceptor();
payloadValidatingInterceptor.setSchema(new ClassPathResource(
"XSD/MySchema.xsd"));
return payloadValidatingInterceptor;
}
}
Sorry but I had to change few of the variable/class names to adhere to company policy. So as you can see I had to put the "not execution" part in the AOP to make my webservice work. If I remove that part, I get 404 error.
回答1:
@Tarun is right, though I also found it necessary to delay the initialization of the AppConfig config
bean.
Because the CustomValidatingInterceptor
bean in your (@hudi's) example is an EndpointInterceptor
, it is needed early in the Spring initialization sequence. This means it is being instantiated before the Aop weaving against the config
bean has taken effect. Note how there is also an EndpointInterceptor
in the original question here.
One way to avoid this is to use an ObjectFactory
. This can be wired in from the start, but enables Spring to delay the actual instantiation of the config
bean, until after the interceptor and Aop proxy are both well initialized.
There's an example of this back on your question. This tested fine from SoapUI.
回答2:
So below is the code you shared
package org.example;
import java.util.List;
import org.aspect.PersistentAspect;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
import javax.annotation.PostConstruct;
@Configuration
@EnableWs
public class WsConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
final MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/v1/*");
}
@Bean
public XsdSchema schema() {
return new SimpleXsdSchema(new ClassPathResource("country.xsd"));
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
String[] jaxbContext = new String[] { "io.spring.guides.gs_producing_web_service" };
marshaller.setContextPaths(jaxbContext);
return marshaller;
}
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
// aop not working
//interceptors.add(new CustomValidatingInterceptor(schema(), config()));
System.out.println("Loading addInterceptors");
interceptors.add(new CustomValidatingInterceptor(schema(), null));
}
@Bean
public AppConfig config() {
System.out.println("Loading config Bean");
return new AppConfig();
}
@PostConstruct
@Bean
public PersistentAspect persistentAspect() {
System.out.println("Loading persistentAspect Bean");
PersistentAspect persistentAspect = new PersistentAspect();
return persistentAspect;
}
@Bean
public Object testAop(AppConfig config) {
System.out.println("is config aop proxy: " + AopUtils.isAopProxy(config));
return config;
}
}
You mentioned that it doesn't works with
interceptors.add(new CustomValidatingInterceptor(schema(), config()));
But works with
interceptors.add(new CustomValidatingInterceptor(schema(), null));
The issues when you call config
manually, the bean is initiated by you and not by Spring and it somehow interferes. You should not initiate the class using the bean method config()
instead use the class directory
interceptors.add(new CustomValidatingInterceptor(schema(), new AppConfig()));
And it work fine
回答3:
Try configuring a PayloadLoggingInterceptor
Check out section "5.5.2.1. PayloadLoggingInterceptor and SoapEnvelopeLoggingInterceptor" in the Spring Reference Docs
来源:https://stackoverflow.com/questions/33492267/spring-soap-webservice-endpoint-with-spring-aop