I am using spring kafka 2.2.8 and trying to implement infinite retry policy using AlwaysRetryPolicy and I've created a custom SeekToCurrentErrorHandler to capture the exception, message key and value during deserialization.
Here is my consumer config code:
#Configuration
#EnableKafka
public class MyKafkaConsumerCommonConfig implements KafkaListenerConfigurer {
private final MySeekToCurrentErrorHandler mySeekToCurrentErrorHandler;
private final MyRecoveryCallback myRecoveryCallback;
private final MyKafkaConsumerRetryPolicy myKafkaConsumerRetryPolicy;
#Autowired
public MyKafkaConsumerCommonConfig(
MySeekToCurrentErrorHandler mySeekToCurrentErrorHandler,
MyRecoveryCallback myRecoveryCallback,
MyKafkaConsumerRetryPolicy myKafkaConsumerRetryPolicy) {
this.mySeekToCurrentErrorHandler = mySeekToCurrentErrorHandler;
this.myRecoveryCallback = myRecoveryCallback;
this.myKafkaConsumerRetryPolicy = myKafkaConsumerRetryPolicy;
}
#Bean
public <K,V> ConcurrentKafkaListenerContainerFactory<String, Object> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(primaryConsumerFactory());
// To achieve Stateful Retry
factory.setStatefulRetry(true);
factory.setErrorHandler(mySeekToCurrentErrorHandler);
// Retry Template
factory.setRetryTemplate(retryTemplate());
//Recovery Call back
factory.setRecoveryCallback(myRecoveryCallback);
return factory;
}
#Bean
public DefaultKafkaConsumerFactory<Object, Object> primaryConsumerFactory() {
return new DefaultKafkaConsumerFactory<>(getConfigs());
}
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setListeners(new RetryListener[]{myKafkaRetryListener});
retryTemplate.setRetryPolicy(myConsumerRetryPolicy);
ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
exponentialBackOffPolicy.setInitialInterval(Long.parseLong(environment.getProperty("MY_KAFKA_RETRY_BACK_OFF_IN_MILLIS", "500")));
//As per the spring-kafka documentation, maxInterval (60000 ms) should be set less than max.poll.interval.ms (600000 ms)
exponentialBackOffPolicy.setMaxInterval(Long.parseLong(environment.getProperty("MY_KAFKA_MAX_RETRY_BACK_OFF_IN_MILLIS", "60000")));
retryTemplate.setBackOffPolicy(exponentialBackOffPolicy);
return retryTemplate;
}
public Map<String, Object> getConfigs() {
Map<String, Object> configs = = new HashMap<>();
configs.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
configs.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer2.class);
configs.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer2.class);
configs.put(ErrorHandlingDeserializer2.KEY_DESERIALIZER_CLASS, stringDeserializerClass);
configs.put(ErrorHandlingDeserializer2.VALUE_DESERIALIZER_CLASS, kafkaAvroDeserializerClass.getName());
sapphireKafkaConsumerConfig.setPartitionAssignmentStrategyConfig(
Collections.singletonList(RoundRobinAssignor.class));
// Set this to true so that you will have consumer record value coming as your pre-defined contract instead of a generic record
sapphireKafkaConsumerConfig.setSpecificAvroReader("true");
}
}
Here is my code for custom RetryPolicy and custom SeekToCurrentErrorHandler.
#Component
public class MyKafkaConsumerRetryPolicy extends ExceptionClassifierRetryPolicy {
private final Environment environment;
public MyKafkaConsumerRetryPolicy(Environment environment) {
this.environment = environment;
}
#PostConstruct
public void init() {
SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
simpleRetryPolicy.setMaxAttempts(Integer.parseInt(environment.getProperty("MY_KAFKA_RETRY_COUNT", "3")));
this.setExceptionClassifier(classifiable ->
{
// Always Retry when instanceOf MyCustomException
if (classifiable.getCause() instanceof MyCustomException) {
return new AlwaysRetryPolicy();
} else if (classifiable.getCause() instanceof DeserializationException) {
return new NeverRetryPolicy();
} else {
return simpleRetryPolicy;
}
});
}
}
#Component
public class MySeekToCurrentErrorHandler extends SeekToCurrentErrorHandler {
private final MyLogger logger;
#Autowired
public MySeekToCurrentErrorHandler(MyLogger logger) {
super(-1);
this.logger = logger;
}
#Override
public void handle(Exception thrownException, List<ConsumerRecord<?, ?>> data,
Consumer<?, ?> consumer, MessageListenerContainer container) {
if(thrownException instanceof DeserializationException){
// This portion would be executed when there is DeserializationException
final String messageKey = (String) data.get(0).key();
logger.logException(thrownException, "DeserializerException occurred for message key"+messageKey, getClass());
System.out.println("messageKey is "+messageKey);
System.out.println("message Value is "+data.get(0).value());
//TODO: Send message to DLT
} else {
//Calling super method to let the 'SeekToCurrentErrorHandler' do what it is actually designed for
super.handle(thrownException, data, consumer, container);
}
}
As you can see above, I'm setting the max attempts to '-1' in my custom SeekToCurrentErrorHandler constructor. Now, to test this, I'm throwing MyCustomException in my consumer which should pick the AlwaysRetryPolicy and trigger infinite retry. But it's retrying only 10 times and stopping. Please suggest, what am i missing here?
} else if (classifiable.getCause() instanceof DeserializationException) {
That will never happen that far up the stack; deserialization exceptions are passed directly to the container's error handler. You already have code in your error handler for that case.
super(-1);
That should work; use a debugger; set a breakpoint in FailedRecordTracker.skip() to see if this.maxFailures is 10; if it is -1, it should always return false.
EDIT
Here's a simpler version of what you have (Spring Boot app) and it works as expected:
#SpringBootApplication
public class So60641945Application {
private static final Logger LOG = LoggerFactory.getLogger(So60641945Application.class);
public static void main(String[] args) {
SpringApplication.run(So60641945Application.class, args);
}
#Bean
public ErrorHandler eh() {
class MyEH extends SeekToCurrentErrorHandler {
MyEH() {
super(-1);
}
#Override
public void handle(Exception thrownException, List<ConsumerRecord<?, ?>> records, Consumer<?, ?> consumer,
MessageListenerContainer container) {
LOG.info("handle");
super.handle(thrownException, records, consumer, container);
}
};
return new MyEH();
}
private final AtomicInteger count = new AtomicInteger();
#KafkaListener(id = "so60641945", topics = "so60641945")
public void listen(String in) {
LOG.info(in + this.count.incrementAndGet());
throw new RuntimeException();
}
#Bean
public NewTopic topic() {
return new NewTopic("so60641945", 1, (short) 1);
}
}
#Component
class FactoryConfigurer {
FactoryConfigurer(ConcurrentKafkaListenerContainerFactory<?, ?> factory) {
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(new AlwaysRetryPolicy());
FixedBackOffPolicy backOff = new FixedBackOffPolicy();
backOff.setBackOffPeriod(1000);
retryTemplate.setBackOffPolicy(backOff);
factory.setRetryTemplate(retryTemplate);
factory.setStatefulRetry(true);
}
}
and
2020-03-11 15:53:23.497 INFO 30480 --- [o60641945-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer-2, groupId=so60641945] Setting newly assigned partitions [so60641945-0]
2020-03-11 15:53:23.519 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo1
2020-03-11 15:53:24.521 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:24.526 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo2
2020-03-11 15:53:25.527 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:25.529 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo3
2020-03-11 15:53:26.534 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:26.537 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo4
2020-03-11 15:53:27.539 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:27.541 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo5
2020-03-11 15:53:28.542 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:28.546 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo6
2020-03-11 15:53:29.549 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:29.552 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo7
2020-03-11 15:53:30.553 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:30.555 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo8
2020-03-11 15:53:31.559 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:31.561 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo9
2020-03-11 15:53:32.562 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:32.564 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo10
2020-03-11 15:53:33.568 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:33.571 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo11
2020-03-11 15:53:34.572 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:34.574 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo12
2020-03-11 15:53:35.577 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:35.580 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo13
2020-03-11 15:53:36.582 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:36.584 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo14
2020-03-11 15:53:37.587 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : handle
2020-03-11 15:53:37.589 INFO 30480 --- [o60641945-0-C-1] com.example.demo.So60641945Application : foo15
...
EDIT2
Embedded kafka:
#RunWith(SpringRunner.class)
#SpringBootTest
public class So60641945ApplicationTests {
#ClassRule
public static EmbeddedKafkaRule embedded = new EmbeddedKafkaRule(1);
#Autowired
private KafkaTemplate<String, String> template;
#Test
public void contextLoads() throws InterruptedException {
this.template.send("so60641945", "bar");
Thread.sleep(30_000);
}
}
spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}
Related
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...
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 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);
}
};
}
}
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();
}
}
i am using spring boot and trying to implement multiple datasources using spring jpa.
Problem when i run server then LocalContainerEntityManagerFactoryBean builds JPA container for Default persistence unit .
i have excluded HibernateJpaAutoConfiguration.class from AutoConfiguration so it should not go for Default datasources? atleast thats what my understanding is.
2015-08-28 08:05:35.933 INFO 3764 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2015-08-28 08:05:35.943 INFO 3764 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
this is how i am running my application
#SpringBootApplication
#Configuration
#EnableAutoConfiguration(exclude = { DataSourceTransactionManagerAutoConfiguration.class,
DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
public class Application extends SpringBootServletInitializer/*
* implements
* CommandLineRunner
*/{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
This is how first Config file looks like :
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "xx.xx.repository", entityManagerFactoryRef = "blueberryEntityManagerFactory", transactionManagerRef = "blueberryTransactionManager")
#PropertySource("classpath:application.properties")
public class DbConfigBlueBerry {
#Value("${spring.datasourceblueberry.driver-class-name}")
String driverClassName = "";
#Value("${spring.datasourceblueberry.url}")
String url = "";
#Value("${spring.datasourceblueberry.username}")
String userName = "";
#Value("${spring.datasourceblueberry.password}")
String password = "";
#Bean(name = "blueberryEntityManager")
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
#Bean(name = "blueberryEntityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(DataSourceBuilder.create().url(url)
.driverClassName(driverClassName).username(userName)
.password(password).build());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
factoryBean.setPackagesToScan(R.Blueberry_PACKAGE);
factoryBean.setPersistenceUnitName("blueberryPersistenceUnit");
Properties jpaProperties = new Properties();
factoryBean.setJpaProperties(jpaProperties);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.MYSQL);
jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
}
#Bean(name = "blueberryTransactionManager")
PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
Note:
LocalContainerEntityManagerFactoryBean builds entityManagerFactory for my defined datasource as well but after building Default one.
Building JPA container EntityManagerFactory for persistence unit 'blueberryPersistenceUnit'
2015-08-28 08:05:36.925 INFO 3764 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: blueberryPersistenceUnit
...]
My Doubts
whats the significance of Default PersistenceUnitInfo ?
From where it is building the Default PersistenceUnitInfo ? What am i missing ?
Please provide your valuable thoughts. Thanks.