6. Implementing Spring Web Services for SOAP
Spring Web Services Introduction
Adding the SOAP Dispatcher Servlet Configuration
To configure the SOAP dispatcher servlet in a Jakarta JEE8 environment, we need to set up the Bootstrap
class and related configuration.
Bootstrap.java
package com.nicordesigns.site.config;
import javax.servlet.FilterRegistration;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import com.nicordesigns.site.filters.AuthenticationFilter;
import com.nicordesigns.site.filters.LoggingFilter;
import com.nicordesigns.site.SessionListener;
public class Bootstrap implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
container.getServletRegistration("default").addMapping("/resources/**");
// Root context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootContextConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
container.addListener(SessionListener.class);
// Dispatcher Servlet for web application
AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
servletContext.register(ServletContextConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet("springDispatcher", new DispatcherServlet(servletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.setMultipartConfig(new MultipartConfigElement(null, 20971520L, 41943040L, 512000));
dispatcher.addMapping("/");
// Logging filter
FilterRegistration.Dynamic loggingFilter = container.addFilter("loggingFilter", new LoggingFilter());
loggingFilter.addMappingForUrlPatterns(null, false, "/*");
// Authentication filter
FilterRegistration.Dynamic authenticationFilter = container.addFilter("authenticationFilter", new AuthenticationFilter());
authenticationFilter.addMappingForUrlPatterns(null, false, "/registration", "/registration/*", "/chat", "/chat/*", "/session", "/session/*");
}
}
ServletContextConfiguration.java
package com.nicordesigns.site.config;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableWebMvc
@EnableWs
@ComponentScan(
basePackages = "com.nicordesigns.site",
useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(Controller.class)
)
public class ServletContextConfiguration implements WebMvcConfigurer {
@Inject
private ObjectMapper objectMapper;
@Inject
private Marshaller marshaller;
@Inject
private Unmarshaller unmarshaller;
@Inject
private SpringValidatorAdapter validator;
@Override
public Validator getValidator() {
return this.validator;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
converters.add(new FormHttpMessageConverter());
converters.add(new SourceHttpMessageConverter<>());
MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
xmlConverter.setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "xml"),
new MediaType("text", "xml")
));
xmlConverter.setMarshaller(this.marshaller);
xmlConverter.setUnmarshaller(this.unmarshaller);
converters.add(xmlConverter);
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
jsonConverter.setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "json"),
new MediaType("text", "json")
));
jsonConverter.setObjectMapper(this.objectMapper);
converters.add(jsonConverter);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorParameter(false)
.parameterName("mediaType")
.ignoreAcceptHeader(false)
.useRegisteredExtensionsOnly(false)
.defaultContentType(MediaType.APPLICATION_XML)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("json", MediaType.APPLICATION_JSON);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
}
@Bean
public LocaleResolver localeResolver() {
return new SessionLocaleResolver();
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/jsp/view/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public DefaultRequestToViewNameTranslator viewNameTranslator() {
return new DefaultRequestToViewNameTranslator();
}
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
// Spring WS Configuration
@Bean(name = "charityRegistration")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema charityRegistrationSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CharityRegistrationPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://nicordesigns.com/ws");
wsdl11Definition.setSchema(charityRegistrationSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema charityRegistrationSchema() {
return new SimpleXsdSchema(new ClassPathResource("xsd/CharityRegistration.xsd"));
}
}
Creating a SoapServletContextConfiguration
package com.nicordesigns.site.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
@Configuration
@ComponentScan(
basePackages = "com.nicordesigns.site.ws",
useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(Endpoint.class)
)
@ImportResource("classpath:com/nicordesigns/site/config/soapServletContext.xml")
public class SoapServletContextConfiguration
{
@Bean
public WebServiceMessageFactory messageFactory()
{
SaajSoapMessageFactory factory = new SaajSoapMessageFactory();
factory.setSoapVersion(SoapVersion.SOAP_12);
return factory;
}
}
Use the XML config file soapServletContext.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
<sws:annotation-driven marshaller="jaxb2Marshaller"
unmarshaller="jaxb2Marshaller" />
<sws:dynamic-wsdl id="charityregistration" portTypeName="CharityRegistration"
locationUri="/services/" createSoap11Binding="false"
createSoap12Binding="true"
targetNamespace="http://nicordesigns.com/xmlns/charityregistration">
<sws:xsd location="/WEB-INF/xsd/CharityRegistration
.xsd" />
</sws:dynamic-wsdl>
</beans>