I'm trying to expose a REST Service which makes available to download a large file streaming, without keeping in memory first. Also I need this to support async calls, if (at least) two users on the same time call this URL should be able both of them to download it.
Application is set up with Spring Boot.
This is what I have on Controller:
#RestController
public class MyController {
private MyService service;
#Autowired
public MyController(MyService service) {
this.service = service;
}
#RequestMapping(
value = "download",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<StreamingResponseBody> downloadAsync() throws IOException {
StreamingResponseBody responseBody = outputStream -> {
service.download(outputStream);
outputStream.close();
};
return ResponseEntity.ok(responseBody);
}
}
This is what I have on Service (download URL is just a sample to test this behavior):
#Service
public class MyService {
private RestTemplate restTemplate;
#Autowired
public MyService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public void download(OutputStream outputStream) {
ResponseExtractor<Void> responseExtractor = clientHttpResponse -> {
InputStream inputStream = clientHttpResponse.getBody();
StreamUtils.copy(inputStream, outputStream);
return null;
};
restTemplate.execute("http://download.thinkbroadband.com/1GB.zip",
HttpMethod.GET,
clientHttpRequest -> {},
responseExtractor);
}
}
In application.yml among others, I have these properties, nothing fancy at all:
server:
port: 9999
context-path: /rest
And this is the JavaConfig file:
#Configuration
public class ApplicationConfig {
#Bean
public RestTemplate restTemplate() {
ClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(HttpClients.createDefault());
RestTemplate restTemplate = new RestTemplate(requestFactory);
restTemplate.setErrorHandler(new ClientErrorHandler());
return restTemplate;
}
}
When I call this endpoint localhost:9999/rest/download download starts and downloads some MBs but after some time, it stops and this is what gets shown on my console:
2017-03-18 17:11:54.808 INFO --- [nio-9999-exec-1] o.a.c.c.C.[.[.[/rest] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-03-18 17:11:54.811 INFO --- [nio-9999-exec-1] o.s.w.s.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-03-18 17:11:54.895 INFO --- [nio-9999-exec-1] o.s.w.s.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 84 ms
2017-03-18 17:12:25.334 ERROR --- [nio-9999-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Async timeout for GET [/rest/download]
2017-03-18 17:12:25.335 WARN --- [nio-9999-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.context.request.async.AsyncRequestTimeoutException
2017-03-18 17:12:25.366 INFO --- [nio-9999-exec-2] o.a.c.c.CoyoteAdapter : Encountered a non-recycled response and recycled it forcedly.
org.apache.catalina.connector.CoyoteAdapter$RecycleRequiredException: null
at org.apache.catalina.connector.CoyoteAdapter.checkRecycled(CoyoteAdapter.java:494) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.http11.Http11Processor.recycle(Http11Processor.java:1627) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.release(AbstractProtocol.java:977) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:869) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_60]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_60]
Can anyone help, please ?
Thanks in advance
If you are encountering this issue using Spring-Boot, it is enough to set the following property to a higher value - for example:
spring:
mvc:
async:
request-timeout: 3600000
or
spring.mvc.async.request-timeout = 3600000
It seems that you run into timeout issues on your async task executor. You can configure the desired timeout (and other settings) with a WebMvcConfigurerAdapter. This code should help resolve this problem. Be sure to replace the ellipsis (...) with the desired values.
This example also registers an interceptor that gets called when there's a timeout in case you want some special handling.
#Configuration
#EnableAsync
#EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
#Override
#Bean(name = "taskExecutor")
public AsyncTaskExecutor getAsyncExecutor() {
log.debug("Creating Async Task Executor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(...);
executor.setMaxPoolSize(...);
executor.setQueueCapacity(...);
executor.setThreadNamePrefix(...);
return executor;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
/** Configure async support for Spring MVC. */
#Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(AsyncTaskExecutor taskExecutor, CallableProcessingInterceptor callableProcessingInterceptor) {
return new WebMvcConfigurerAdapter() {
#Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(...)
.setTaskExecutor(taskExecutor);
configurer.registerCallableInterceptors(callableProcessingInterceptor);
super.configureAsyncSupport(configurer);
}
};
}
#Bean
public CallableProcessingInterceptor callableProcessingInterceptor() {
return new TimeoutCallableProcessingInterceptor() {
#Override
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
log.error("timeout!");
return super.handleTimeout(request, task);
}
};
}
}
Related
Good day, I have the application with microservices and gateway (zuul) built on SpringBoot 2. It is all uses SSL.
I need the automatic redirect from: http:\\localhost (currently shows nothing) to https:\\localhost (shows some text), so the user doesn't need to bother.
Once again: http:\\localhost has to show the same text as https:\\localhost (I need a redirect)
I've tried, does nothing.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel().anyRequest().requiresSecure();
}
}
Tried another approach, but SpringBoot failed to recognize TomcatEmbeddedServletContainerFactory
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(createHttpConnector());
return tomcat;
}
private Connector createHttpConnector() {
Connector connector
= new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setSecure(false);
connector.setPort(8080);
connector.setRedirectPort(8443);
return connector;
}
this one doesn't work either (doesn't seems to change anything)
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment environment;
#Override
public void configure(HttpSecurity http) throws Exception {
// other security configuration missing
http.portMapper()
.http(80) // http port defined in yml config file
.mapsTo(443); // https port defined in yml config file
// we only need https on /auth
http.requiresChannel()
.antMatchers("/auth/**").requiresSecure()
.anyRequest().requiresInsecure();
}
}
and this one ain't working too, the error is Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
#Bean
public TomcatServletWebServerFactory httpsRedirectConfig() {
return new TomcatServletWebServerFactory () {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
}
and even this one with the java.lang.IllegalStateException: No ServletContext set error
#Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(80);
connector.setSecure(false);
connector.setRedirectPort(443);
return connector;
}
Any suggestions?
Got it.
Thanks to EstebanGarciaAlonso and his answer ugrade spring boot 2.0.0.RC2 exception No ServletContext set
"After debugging, the problem is that mvc configuration class
EnableWebMvcConfiguration load too early, servlet not loaded yet."
I spent a few hours on this. I managed to find a reason why this was
happening. My config was split into several files and I was creating a
MVC related bean in the Security Config (which was created earlier)
forcing to use the MVC config before its time.
The solution was to move the #Bean instance from the security config
to the MVC config. I hope it helps other people!
I moved following code to Application.java just before main method and all worked like miracle
#Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(80);
connector.setSecure(false);
connector.setRedirectPort(443);
return connector;
}
This question already has answers here:
Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?
(13 answers)
Closed 4 years ago.
I am new to spring MVC and I am trying to build an application. However, while running the application I am getting an error that "No mapping found for HTTP request with URI".
I am including my code and console log as well.
Please help me to sort this out
This is my Web App Initializer class
public class SpringWebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDisptacher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
// UtF8 Charactor Filter.
FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/");
}
}
This is my ApplicationContextConfig Class
#Configuration
#ComponentScan("com.wfm.account.*")
#EnableTransactionManagement
public class ApplicationContextConfig {
#Autowired
private static Environment env;
private static final String JDBC_DRIVER_CLASS = "oracle.jdbc.driver.OracleDriver";
private static final String JDBC_URL = "URL";
private static final String DB_USERNAME = "cisadm";
private static final String DB_PASSWORD = "PASSWORD";
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//Set Driver properties
dataSource.setDriverClassName(JDBC_DRIVER_CLASS);
dataSource.setUrl(JDBC_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
System.out.println("Data Source is : " + dataSource);
return (DataSource) dataSource;
}
#Bean(name = "transactionManager")
public DataSourceTransactionManager getTransactionmanagerDataSource() {
DataSourceTransactionManager txManager = new DataSourceTransactionManager();
DataSource dataSource = this.getDataSource();
txManager.setDataSource(dataSource);
return txManager;
}
}
This is my Controller
public class UserController {
#Autowired
private UserDao userDao;
#RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String welcome(Model model) {
userDao.insertUser("SYSUSER", "sysuer15", "abc#com.au", "0893266188");
User userDetails = userDao.findUser("N018003");
model.addAttribute("user", userDetails);
return "welcome";
}
}
This console log
16:36:06.795 [main] DEBUG o.s.web.servlet.DispatcherServlet - Published WebApplicationContext of servlet 'SpringDisptacher' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.SpringDisptacher]
16:36:06.797 [main] INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'SpringDisptacher': initialization completed in 2828 ms
16:36:06.798 [main] DEBUG o.s.web.servlet.DispatcherServlet - Servlet 'SpringDisptacher' configured successfully
Dec 20, 2018 4:36:06 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Dec 20, 2018 4:36:06 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-nio-8009"]
Dec 20, 2018 4:36:06 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in [11,285] milliseconds
16:36:08.335 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'SpringDisptacher' processing GET request for [/WorkforceManagement/]
16:36:08.355 [http-nio-8080-exec-2] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/WorkforceManagement/] in DispatcherServlet with name 'SpringDisptacher'
16:36:08.356 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
As I have gone through your code, everything seems perfect except:-
#EnableWebMvc for ApplicationContextConfig file.
#Controller for UserController file.
I have developed my simple solution using your code, you can find it below:-
Configuration class:-
#EnableWebMvc
#Configuration
#ComponentScan("com.sof.controller")
public class ApplicationContextConfig {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
SpringWebAppInitializer class:-
public class SpringWebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDisptacher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
UserController class
#Controller
public class UserController {
#RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String welcome(Model model) {
// userDao.insertUser("SYSUSER", "sysuer15", "abc#com.au", "0893266188");
// User userDetails = userDao.findUser("N018003");
model.addAttribute("user", "Hi Roumil");
return "welcome";
}
}
Source code of this Project
If you have any more queries, I would be glad to help you out...
I am trying to update an audit entry using the response body advice but as far as I can tell it never gets executed. I see the bean in the logs:
{"timestamp":"2018-08-21T15:48:08.349Z","level":"INFO","thread":"main",
"logger":"org.springframework.data.rest.webmvc.RepositoryRestHandlerAdapter",
"message":"Detected ResponseBodyAdvice bean in responseAuditAdvice","context":"default"}
My controller method looks like this:
#PostMapping(path = "/stage", consumes = {
"application/json"
}, produces = {
"application/json"
})
#ResponseBody
public ResponseEntity<?> stage(#Valid #RequestBody StagingDto stagingDto,
#RequestHeader(HttpHeaders.USER_AGENT) String userAgent,
BindingResult bindingResult) {
I have a RequestAuditAdvice that extends RequestBodyAdviceAdapter and it is working fine. Also if the error flow occurs I see the exception advice executing as well. it is only the response advice that is failing to trigger. Any suggestions?
here is the advice bean:
#Slf4j
#RequiredArgsConstructor(onConstructor_ = #Inject)
#ControllerAdvice
public class ResponseAuditAdvice implements ResponseBodyAdvice<Object> {
private final RequestService requestService;
#Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
log.info("Updating audit for response.");
String ip = new String (request.getRemoteAddress().getAddress().getAddress());
requestService.auditResponse(ip, 200);
return body;
}
}
Given below code for Controller, when I start the spring boot application, I am able to make http calls to the resource /foo/id/{id} to fetch data.
However the same call from an Integration test is returning 404. Call did not trigger rest controller method. Test is not forwarding the http calls to the rest controller. What am I missing?
#RestController
#RequestMapping(“/foo”)
class FooResource {
#RequestMapping(method = RequestMethod.GET, path = “/id/{id}”)
String getData(#PathVariable int id) {
logger.error("===== FooResource.getData called with {}", id)
// more code
}
//more code
//Spock test case
#ContextConfiguration
#SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
#EnableWebMvc
#AutoConfigureWebClient
#TestPropertySource(locations = "classpath:application-test.properties")
class IntegrationTest extends Specification {
#Autowired
RestTemplate restTemplate
#Configuration
#ImportResource(["classpath*:/test-properties.xml", "classpath*:/springintegration-config.xml"])
static class Beans {
#Bean
MessagingTemplate messagingTemplate() { new MessagingTemplate() }
#Bean
ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory(9010);
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(30 * 1000)
.setReadTimeout(30 * 1000)
.build();
}
}
def ‘foo resource returns the expected data for Id'() {
given:
int id = new SecureRandom().nextInt()
TestRestTemplate restTemplate = new TestRestTemplate();
when:
ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:9010/foo/id/1234", String.class)
then:
assert response.statusCode == HttpStatus.OK
}
Test case run log includes the below mappings already available
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped “{[/foo/id/{Id}],methods=[GET]}" onto public java.lang.String com.foo.bar.rest.FooResource.getData(int)
2018-06-15 13:54:38.680 DEBUG 20710 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'requestMappingHandlerMapping'
2018-06-15 13:54:38.680 DEBUG 20710 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'mvcPathMatcher'
2018-06-15 13:54:38.681 DEBUG 20710 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'mvcPathMatcher'
Changing the Annotations on IntegrationTest class resolved the issue.
//Spock test case
#SpringBootTest(
classes = TestConfig.class,
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
#AutoConfigureWebClient
#TestPropertySource(locations = "classpath:application-test.properties")
class IntegrationTest extends Specification {
#Autowired
RestTemplate restTemplate
#Configuration
#ImportResource(["classpath*:/test-properties.xml", "classpath*:/springintegration-config.xml"])
static class Beans {
#Bean
MessagingTemplate messagingTemplate() { new MessagingTemplate() }
#Bean
ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory(9010);
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(30 * 1000)
.setReadTimeout(30 * 1000)
.build();
}
}
def ‘foo resource returns the expected data for Id'() {
given:
int id = new SecureRandom().nextInt()
TestRestTemplate restTemplate = new TestRestTemplate();
when:
ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:9010/foo/id/1234", String.class)
then:
assert response.statusCode == HttpStatus.OK
}
I'm trying to consume some SOAP web services within a spring boot application. I've imported the ws's stubs and I've followed WebServiceTemplate, as explained here. Unfortunately, when making requests I get an exception:
2017-01-13 12:13:47.146 ERROR 1300 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: no se ha podido canalizar el tipo "com.dashboard.dto.ComprobarSolicitud" como un elemento, porque le falta una anotación #XmlRootElement]] with root cause
The "ComprobarSolicitud" class is the following one:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "comprobarSolicitud", propOrder = {
"username",
"passwd",
"nif",
"fechaDesde",
"fechaHasta",
"cantidad"
})
public class ComprobarSolicitud {
protected String username;
protected String passwd;
protected String nif;
protected String fechaDesde;
protected String fechaHasta;
protected int cantidad;
// ...getters and setters
WebServiceGatewaySupport class:
public class PerClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(PadronClient.class);
public ComprobarSolicitudResponse comprobarSolicitudes(String pNif, LocalDate pFechaInicio, LocalDate pFechaFin){
ComprobarSolicitud request = new ComprobarSolicitud();
// .. set operations to request
ComprobarSolicitudResponse response = (ComprobarSolicitudResponse) getWebServiceTemplate()
.marshalSendAndReceive(
"https://ws.dir.com:8444/PerExterno/perExterno",
request,
new SoapActionCallback("http://service.ws.per.company.com/ExternalWS/comprobarSolicitudResponse"));
return response;
}
}
Configuration class:
#Configuration
public class PerConfiguration {
#Bean
public Jaxb2Marshaller marshaller(){
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.dashboard.dto.per");
return marshaller;
}
#Bean
public PerClient padronClient(Jaxb2Marshaller marshaller){
PerClient client = new PerClient();
client.setDefaultUri("https://ws.dir.com:8444/PerExterno");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
Should I create a custom marshaller? But, how? I've found this, where it's said that in case #XmlRootElement annotation is missing, I should wrap it in an instance of JAXBElement.
Thank you
SOLUTION!
The exception was self-explanatory, and the solution was straightforward, as just PerClient class was necessary to be modified as follows:
public class PerClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(PadronClient.class);
public ComprobarSolicitudResponse comprobarSolicitudes(String pNif, LocalDate pFechaInicio, LocalDate pFechaFin){
ComprobarSolicitud request = new ComprobarSolicitud();
// .. set operations to request
ObjectFactory of = new ObjectFactory();
JAXBElement<ComprobarSolicitud> reqjaxb = of.createComprobarSolicitud(request);
#SuppressWarnings("unchecked")
JAXBElement<ComprobarSolicitudResponse> response = (ComprobarSolicitudResponse) getWebServiceTemplate()
.marshalSendAndReceive(
"https://ws.dir.com:8444/PerExterno/perExterno",
reqjaxb ,
new SoapActionCallback("http://service.ws.per.company.com/ExternalWS/comprobarSolicitudResponse"));
return response.getValue();
}
}