Exception: multipart/form-data request failed in Spring Boot - spring

tech stack: Java 14, Spring Boot 2.5.3, MySQL 8.0.26, JPA
I'v got a spring boot uploading Excel web application. Excel file with 14KB capacity was uploaded successfully. However, if you try to upload an Excel file with 15MB and 50MB capacity, the following exception occurs.
I guess that server connection timed out when uploading. I guess the server to be closed before file is uploaded due to the short server connection time. To solve this problem, I tried to change the server settings in application.properties. I found some property. But it was not proper. The IDE underlines like this. I also visited Spring Common Application Properties Page to find the appropriate property, but I couldn't find it.
I would like to know what causes the exception. And I wonder if this is the right way to solve the problem.
Thank you in advance. If you reply, I will reply as soon as possible.
exception console
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.impl.IOFileUploadException: Processing of multipart/form-data request failed. java.io.EOFException] with root cause
java.io.EOFException: null
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1294) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1206) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:805) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.access$300(Http11InputBuffer.java:42) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer$SocketInputBuffer.doRead(Http11InputBuffer.java:1172) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:101) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.http11.Http11InputBuffer.doRead(Http11InputBuffer.java:249) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.coyote.Request.doRead(Request.java:640) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:317) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.checkByteBufferEof(InputBuffer.java:600) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:340) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:132) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:975) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:879) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:132) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:132) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:106) ~[na:na]
at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:98) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:291) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.Request.parseParts(Request.java:2922) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.Request.getParts(Request.java:2824) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:95) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:88) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:122) ~[spring-web-5.3.9.jar:5.3.9]
at ...
application.properties
server.tomcat.connection-timeout is right. But server.tomcat.disable-upload-timeout and server.connectionUploadTimeout are not proper.
server.tomcat.connection-timeout=5000
server.tomcat.disable-upload-timeout=false
server.connectionUploadTimeout=5000
# MultiPart
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
controller
package com.nc.ojtfirstproject.web;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.nc.ojtfirstproject.message.ResponseMessage;
import com.nc.ojtfirstproject.service.StandardProductService;
#Controller
public class StandardProductController {
private final StandardProductService standardProductService;
public StandardProductController(StandardProductService standardProductService) {
this.standardProductService = standardProductService;
}
#PostMapping("/excel/upload")
public ResponseEntity<ResponseMessage> uploadFile(#RequestParam("file") MultipartFile file) {
String TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpStatus status = HttpStatus.OK;
String message = "";
if (TYPE.equals(file.getContentType())) {
try {
standardProductService.save(file);
status = HttpStatus.OK;
message = "success: " + file.getOriginalFilename();
} catch (Exception e) {
status = HttpStatus.EXPECTATION_FAILED;
message = "fail: " + file.getOriginalFilename();
}
} else {
status = HttpStatus.BAD_REQUEST;
message = "Please upload excel file";
}
return ResponseEntity.status(status).body(new ResponseMessage(message));
}
}
service
package com.nc.ojtfirstproject.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.nc.ojtfirstproject.domain.standardProduct.StandardProduct;
import com.nc.ojtfirstproject.domain.standardProduct.StandardProductRepository;
#Service
public class StandardProductService {
private final StandardProductRepository standardProductRepository;
public StandardProductService(StandardProductRepository standardProductRepository) {
this.standardProductRepository = standardProductRepository;
}
#Transactional
public void save(MultipartFile file) {
final int TRANSACTION_CHUNK_LIMIT = 10000;
List<StandardProduct> standardProductList = new ArrayList<StandardProduct>();
try {
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
Row row = sheet.getRow(i);
StandardProduct standardProduct = new StandardProduct();
standardProduct.setCode((int) row.getCell(0).getNumericCellValue());
standardProduct.setCategoryCode((int) row.getCell(1).getNumericCellValue());
standardProduct.setName(row.getCell(2).getStringCellValue());
standardProduct.setLowestPrice((int) row.getCell(3).getNumericCellValue());
standardProduct.setMobileLowestPrice((int) row.getCell(4).getNumericCellValue());
standardProduct.setAveragePrice((int) row.getCell(5).getNumericCellValue());
standardProduct.setCompanies((int) row.getCell(6).getNumericCellValue());
standardProductList.add(standardProduct);
// TRANSACTION_CHUNK_LIMIT saveAll()
if (TRANSACTION_CHUNK_LIMIT == standardProductList.size()) {
standardProductRepository.saveAll(standardProductList);
standardProductList.clear();
System.out.println(TRANSACTION_CHUNK_LIMIT + " success");
}
}
workbook.close();
} catch (IOException e) {
throw new RuntimeException("save fail: " + e.getMessage());
}
// TRANSACTION_CHUNK_LIMIT saveAll()
try {
standardProductRepository.saveAll(standardProductList);
} catch (Exception e) {
throw new RuntimeException("save fail: " + e.getMessage());
}
}
}
build.gradle
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.nc'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'org.apache.poi:poi:4.1.2'
implementation 'org.apache.poi:poi-ooxml:4.1.2'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}

I had similar error and updated the following configuration parameters in the application.properties file like so:
spring.servlet.multipart.max-file-size=XX MB
spring.servlet.multipart.max-request-size=XX MB
server.tomcat.connectionUploadTimeout=XXX (in miliseconds)
server.tomcat.connectionTimeout=XXX (in miliseconds)
server.tomcat.connection-timeout=XXX (in miliseconds)
server.tomcat.max-swallow-size=XX MB
server.tomcat.max-http-form-post-size=XX MB
server.tomcat.background-processor-delay=XXX (in miliseconds)
server.tomcat.keep-alive-timeout=XXX (in miliseconds)
server.tomcat.max-swallow-size=XXX MB
Setting these parameters like shown should solve the problem.

Related

Grails Spring Batch plugin not finding jobs

I'm working on a project with Grails 3.3.7 and I'm trying to get the Spring Batch to work using the grails-spring-batch. Just like in the documentation example, I created a MySimpleJobBatchConfig.groovy file in the grails-app/batch directory with the following content :
import myapp.PrintMessageTasklet;
beans {
xmlns batch:"http://www.springframework.org/schema/batch"
batch.job(id: 'mySimpleJob') {
batch.step(id: 'logStart') {
batch.tasklet(ref: 'printMessage')
}
}
printMessage(PrintMessageTasklet) { bean ->
bean.autowire = "byName"
}
}
PrintMessageTasklet is defined as such in src/main/groovy/myapp/PrintMessageTasklet.groovy :
package myapp
import org.springframework.batch.core.StepContribution
import org.springframework.batch.core.scope.context.ChunkContext
import org.springframework.batch.core.step.tasklet.Tasklet
import org.springframework.batch.repeat.RepeatStatus
class PrintMessageTasklet implements Tasklet {
RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) {
println "Test"
return RepeatStatus.FINISHED
}
}
And here's the service that's trying to launch the job in grails-app/services/myapp/SimpleJobService :
package myapp
import grails.gorm.transactions.Transactional
import org.springframework.batch.core.JobParameters
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing
#Transactional
class SimpleJobService {
def jobLauncher;
def mySimpleJob;
def launchSimpleJob() {
jobLauncher.run(mySimpleJob, new JobParameters())
}
}
However, when I run launchSimpleJob, I get the following exception telling me that mySimpleJob is null, despite me having defined it in the MySimpleJobBatchConfig.groovy file.
java.lang.reflect.InvocationTargetException: null
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.IllegalArgumentException: The Job must not be null.
at org.springframework.util.Assert.notNull(Assert.java:134)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:94)
at myapp.SimpleJobService.$tt__launchSimpleJob(SimpleJobService.groovy:14)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at myapp.SimpleJobController.launch(SimpleJobController.groovy:9)
... 14 common frames omitted
If I try to start my job using springBatchService.launch('mySimpleJob') instead, the message in the returned map also tells me that it couldn't find the job named "mySimpleJob".
Since I'm quite new to Groovy and Spring Batch and I followed carefully the documentation of this plugin I can't find what's wrong. Does anyone knows how to fix this ?
Fixed it, the plugin documentation was outdated, turns out my BatchConfing needed to be in the src/main/resources/batch folder instead of the grails-app/batch folder.
Also had to change #Transactional to #Transactional(propagation = Propagation.NOT_SUPPORTED) in my service.

spring-boot, Jetty setup results in authenticated failed for username Already authenticated as UNAUTHENTICATED

i am doing migration from jboss to jetty and during login it fails see stacktrace bellow at the end.
I am using a OncePerRequestFilter where I am invoking request.login(requestEksternSsoToken, null);
and then it says I am already authenticated as UNAUTHENTICATED. What is the problem and how can I fix it ?
14:05:05.602 [qtp1288135425-15] DEBUG n.n.m.s.filter.OpenAMLoginFilter - Login failed.
org.eclipse.jetty.server.Authentication$Failed: Authenticated failed for username 'AQIC5wjhfjsdhfjksdhfjadshfjdhssjdfhasdkhf'. Already authenticated as UNAUTHENTICATED
at org.eclipse.jetty.server.Request.login(Request.java:2530)
at xx.xxxx.xxxx.security.filter.OpenAMLoginFilter.login(OpenAMLoginFilter.java:165)
at xx.xxx.xxxx.security.filter.OpenAMLoginFilter.handleNoExistingLogin(OpenAMLoginFilter.java:95)
at xx.xxxxx.xxxxx.security.filter.OpenAMLoginFilter.doFilterInternal(OpenAMLoginFilter.java:71)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1435)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1350)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:516)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:388)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:633)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:380)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:882)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1036)
at java.base/java.lang.Thread.run(Thread.java:829)
UPDATE:
Here I have written a configuration of Jetty where I am configuring security constraint still it is throwing the same error in my filter when I attempt to invoke login.
#Configuration
public class JettyConfig {
private static final Logger logger = getLogger(JettyConfig.class);
#Bean
WebServerFactoryCustomizer embeddedServletContainerCustomizer(final JettyServerCustomizer jettyServerCustomizer) {
return container -> {
if (container instanceof JettyServletWebServerFactory) {
logger.info("Adding jetty server customizer");
((JettyServletWebServerFactory) container).addServerCustomizers(jettyServerCustomizer);
}
};
}
#Bean
JettyServerCustomizer jettyServerCustomizer(final LoginService loginService,ConstraintSecurityHandler constraintSecurityHandler) {
return server -> {
logger.info("Setting loginService");
((WebAppContext) server.getHandler()).setSecurityHandler(constraintSecurityHandler);
};// .setSecurityHandler(constraintSecurityHandler);
}
#Bean
ConstraintSecurityHandler constraintSecurityHandler(final LoginService loginService) {
final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.setLoginService(loginService);
Constraint constraint = new Constraint();
constraint.setName("Auth");
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/*");
mapping.setConstraint(constraint);
securityHandler.addConstraintMapping(mapping);
securityHandler.setLoginService(loginService);
return securityHandler;
}
#Bean
LoginService loginService() {
JAASLoginService jaas = new JAASLoginService("OpenAM Realm");
jaas.setLoginModuleName("openam");
return jaas;
}
I was able to find the problem on my own. It apears that in contrast to Embeded Jetty deployment the webapp/web-inf directory is not exmploded and then spring boot is not able to find the jaas login.conf file and it is failing to load the login module silently. Setting explicitly the configuration from a location resolves the issue:
JAASLoginService jaas = new JAASLoginService("OpenAM Realm");
jaas.setLoginModuleName("openam");
final String loginConfFile = "/app/login.conf";//Applcation.class.getClassLoader().getResource("login.conf").getFile();
logger.info("login.conf file location is " + loginConfFile);
File file = (new File(loginConfFile));
logger.info("uri is " + file.toURI());
ConfigFile configfile = new ConfigFile(file.toURI());
jaas.setConfiguration(configfile);

The import org.springframework.boot.test cannot be resolved

I am currently working on a Spring application using SpringBoot. To manage depedencies of this project, I'm using Gradle.
I wanted to implement some tests but I got this error: "The import org.springframework.boot.test cannot be resolved".
Here is the code.
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
class ClassTest {
#Test
public void contextLoads() {
}
}
And the content of the build.gradle
plugins {
id "com.moowork.gulp" version "1.2.0"rk.node" version "1.2.0"
id "org.springframework.boot" version "2.1.5.RELEASE"
id "java"
}
configurations {
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
test {
useJUnitPlatform()
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-web"
developmentOnly "org.springframework.boot:spring-boot-devtools"
testImplementation "org.springframework.boot:spring-boot-starter-test"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf"
implementation "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
testCompile "org.junit.jupiter:junit-jupiter:5.4.2"
annotationProcessor "org.projectlombok:lombok"
implementation "org.projectlombok:lombok"
implementation "org.apache.commons:commons-csv:1.1"
implementation "org.apache.commons:commons-math3:3.0"
}
The simplified stack trace is the following:
java.lang.Error: Unresolved compilation problems:
The import org.springframework.boot.test cannot be resolved
The import org.springframework.test cannot be resolved
SpringRunner cannot be resolved to a type
Class<SpringRunner> cannot be resolved to a type
SpringBootTest cannot be resolved to a type
at climenvi.webapp.ClassTest.<init>(ClassTest.java:12)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
I have tried some solutions found already for this but nothing corrected the problem. Could you help me please ? Thank you for your help.

"Could not return the resource to the pool" error with Spring and Redis

I was trying to implement Redis with Spring with XML based configuration. My configuration file like as below:
<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
c:template-ref="redisTemplate" />
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="172.17.0.2" p:use-pool="true" />
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory" />
And my cache definitions like:
#Cacheable(value = "my-cache-key", key = "{#argSomeObj, #argSomeString, #argSomeInt}")
public MyAwesomeDTO getSomeResult(SomeObject argSomeObj, String argSomeString, int argSomeInt, Request argRequest)
{
// this part calculates and returns some values regarding to given parameters
return awesomeDTO;
}
When I hit this function in first time I got error which is stated below. When I try second time, it works properly and stores in Redis.
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:103)
at redis.clients.jedis.JedisPool.returnBrokenResource(JedisPool.java:239)
at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:255)
at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:16)
at org.springframework.data.redis.connection.jedis.JedisConnection.close(JedisConnection.java:257)
at org.springframework.data.redis.core.RedisConnectionUtils.releaseConnection(RedisConnectionUtils.java:206)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:205)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153)
at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:140)
at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:125)
at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:82)
at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:651)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:358)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:299)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
Is there anybody knows how can I fix this error?
Here is the full stack trace:
01-30 12:34:35 [Thread#12:34:35.259:https://www.vtokmak.office.com:8443/some-url] ERROR com.tokmak.frontend.MyApplication - A 500 error (redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool) occured on URL [https://www.vtokmak.office.com:8443/some-url], userAgent [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36]
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:103)
at redis.clients.jedis.JedisPool.returnBrokenResource(JedisPool.java:239)
at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:255)
at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:16)
at org.springframework.data.redis.connection.jedis.JedisConnection.close(JedisConnection.java:257)
at org.springframework.data.redis.core.RedisConnectionUtils.releaseConnection(RedisConnectionUtils.java:206)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:205)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153)
at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:140)
at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:125)
at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:82)
at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:651)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:358)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:299)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.tokmak.frontend2.service.misc.world.WorldService$$EnhancerBySpringCGLIB$$8a70244e.getWorld(<generated>)
at com.tokmak.frontend2.controller.world.AbstractWorldController.handle(AbstractWorldController.java:69)
at com.tokmak.frontend.Router.getView(Router.java:1069)
at com.tokmak.frontend.Router.routeRequest(Router.java:320)
at com.tokmak.webframework.RouterServlet.doRequestProcessingUnchecked(RouterServlet.java:145)
at com.tokmak.webframework.RouterServlet.doRequestProcessing(RouterServlet.java:93)
at com.tokmak.webframework.RouterServlet.doGet(RouterServlet.java:68)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Invalidated object not currently part of this pool
at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:640)
at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:101)
... 44 more
// 01-30 12:34:35 [Thread#12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN com.tokmak.webframework.RouterServlet - Exception [/some-url], message: "Could not return the resource to the pool"]
01-30 12:34:35 [Thread#12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN com.tokmak.frontend.Router - I have to make use of static fail over [http://192.168.3.14/]...
01-30 12:34:35 [Thread#12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN com.tokmak.frontend.Router - ... but since there is a static fail-over URL present in config, I try to load the data from [http://192.168.3.14/www.vtokmak.office.com:8443/some-url]
01-30 12:34:35 [Thread#12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN com.tokmak.frontend.Router - fuck, even though I have a static fail-over URL, I failed!
Jan 30, 2018 12:34:36 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
although I can't see your code, I've seen this happen when you try to close a jedis instance twice, without noticing. for eg:
Jedis implements Closable and when inside a try-with-Resources it will be automatically closed.
try(Jedis jedis = getJedis()){
}catch{...}
thus if you also call jedis.close() it will throw that error.
either
try{
Jedis jedis = getJedis();
}catch(){
}finally{
jedis.close()
}
or see if you're calling close() more than once
As #mp911de mentioned here, this problem was related to Spring Data Redis version. When I upgraded it resolved.
Here is the java based configuration. Try and share results.
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import redis.clients.jedis.JedisPoolConfig;
#Configuration
#EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
#Override
#Bean
public CacheManager cacheManager() {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate());
cacheManager.setUsePrefix(true);
//cacheManager.setCacheNames(getCacheNames());
return cacheManager;
}
#Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setExposeConnection(true);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
om.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
om.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
om.setSerializationInclusion(Include.NON_NULL);
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setEnableDefaultSerializer(true);
return redisTemplate;
}
#Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisPoolConfig config = new JedisPoolConfig();
config.setTestOnBorrow(false);
config.setTestOnCreate(false);
config.setTestOnReturn(false);
config.setTestWhileIdle(false);
config.setMaxTotal(1000);
config.setMaxIdle(1000);
config.setMinIdle(0);
config.setMaxWaitMillis(10000);
JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
connectionFactory.setHostName("172.17.0.2");
//connectionFactory.setPort(6379);
connectionFactory.setUsePool(true);
connectionFactory.setPoolConfig(config);
return connectionFactory;
}
#Override
#Bean
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
}

spring boot and camel throws direct.DirectConsumerNotAvailableException

I'm trying to get simple example of springboot and camel working but come undone. Not sure what i'm doing wrong. in the gradle build i've included so far
dependencies {
compile 'org.apache.camel:camel-spring-boot-starter:2.18.4'
compile 'org.apache.camel:camel-groovy:2.18.4'
compile 'org.apache.camel:camel-stream:2.18.4'
compile 'org.codehaus.groovy:groovy-all:2.4.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
i've create a DirectRoute component like this
#Component
class DirectRoute extends RouteBuilder{
#Override
void configure () throws Exception {
from ("direct:in") //tried stream:in also
.to ("stream:out")
}
}
I then have a driver bean that try's to invoke the route
#Component
public class HelloImpl implements Hello {
#Produce(uri = "direct:in")
private ProducerTemplate template;
#Override
public String say(String value) throws ExecutionException, InterruptedException {
assert template
println "def endpoint is : " + template.getDefaultEndpoint()
return template.sendBody (template.getDefaultEndpoint(), value)
}
}
lastly in the springboot application class i added a command line runner like this, that gets my bean from the spring context, and invokes the say method. I'm using groovy so i just passed a closure to the command line runner.
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
//return closure to run on startup - just list the beans enabled
{args ->
println("Let's inspect the beans provided by Spring Boot:")
String[] beanNames = ctx.getBeanDefinitionNames()
Arrays.sort(beanNames)
for (String beanName : beanNames) {
println(beanName)
}
println("call the direct:start route via the service")
Hello service = ctx.getBean("helloService")
def result = service.say("William")
println "service returned : $result "
}
}
when i run my application i get all the bean names printed out (that's ok), however when i invoke the direct:in via producer template i get this error (org.apache.camel.component.direct.DirectConsumerNotAvailableException) see below.
I was expecting the route to be triggered the name sent to see that arrive in the output stream - but this is what i get.
Caused by: org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-MONSTER-PC2-58911-1496920205300-0-2]
at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1795) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:677) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:515) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:511) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:163) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.ProducerTemplate$sendBody$0.call(Unknown Source) ~[na:na]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) [groovy-all-2.4.11.jar:2.4.11]
at services.HelloImpl.say(HelloImpl.groovy:29) ~[main/:na]
at services.Hello$say.call(Unknown Source) ~[na:na]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-all-2.4.11.jar:2.4.11]
at application.Application$_commandLineRunner_closure1.doCall(Application.groovy:47) ~[main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.Closure.call(Closure.java:414) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124) ~[groovy-all-2.4.11.jar:2.4.11]
at com.sun.proxy.$Proxy44.run(Unknown Source) ~[na:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
... 10 common frames omitted
Caused by: org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint: direct://in. Exchange[ID-MONSTER-PC2-58911-1496920205300-0-2]
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:55) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:529) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:497) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:365) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:497) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:225) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:144) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:161) ~[camel-core-2.18.4.jar:2.18.4]
What have i done wrong - and why does the producer template invocation on 'direct:in' (also tried stream in with same problem) not work? I thought that .to("stream:out") would be a consumer.
any pointers or advice gratefully received at this point
I have an update on my problems:
I had a subpackage with the application class annotated with #SpringBootApplication. So yes, unadorned it only scans subpackages.
you can add scanBasePackages= or scanBaseClasses= parameter, however when I tried doing a scan for single class, it seemed to scan the whole directory any way and grabbed the others as well.
I refactored the app to have a single root package with subpackages and elected to set the 'scanBasePakages to the new root package. but left the Application class in its own subpackage (personal preference only - documentation suggests leaving the Application in the root package)
you can now add other classes annotated with #Configuration to generate beans or use the basic #Component.
if you create Camel routes annotated with #Component they will be auto configured in the camelContext for you.
it appears by default that Spring isnt not starting the camelContext for you. When I checked the status of the context it shows as starting and not started. so in my commandLineRunner I had to start get the spring injected camelContext and had to start it myself, and exited it when I finished. I was slightly suprised as I thought SpringBootStarter would auto start the camelContext, but it appears not.
once you have Spring component scanning etc working and you start the camelContext, then problems with the org.apache.camel.component.direct.DirectConsumerNotAvailableException exception went away and things started to work - at least the baby examples I'm trying.
So revised structure now looks like this:
The revised ApplicationClass now looks like this with some simple println output to see the state of the context, and beans in the spring ctx. The helleoService bean is still the proxy I use to setup the producer template to call the DirectRoute.
package com.softwood.application
import groovy.util.logging.Slf4j
import org.apache.camel.CamelContext
import org.springframework.beans.factory.annotation.Autowired
import com.softwood.services.Hello
/**
* Created by willw on 07/06/2017.
*/
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean
#Slf4j //inject logger
#SpringBootApplication (scanBasePackages = ["com.softwood"]) //forces scan at parent
// same as #Configuration #EnableAutoConfiguration #ComponentScan with 'defaults' e.g. sub packages
public class Application {
#Autowired
ApplicationContext ctx
#Autowired
CamelContext camelContext
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
//return closure to run on startup - just list the beans enabled
{args ->
println("Let's inspect the beans provided by Spring Boot:")
String[] beanNames = ctx.getBeanDefinitionNames()
Arrays.sort(beanNames)
for (String beanName : beanNames) {
println(beanName)
}
/* when component scan is working - bean routes are added
automatically to camel context via springBoot, however you do have to start
the camel context, yourself
*/
println "camelCtx has following components : " + camelContext.componentNames
println "camelCtx state is : " + camelContext.status
println "starting camel context"
camelContext.start()
println "camelCtx state now is : " + camelContext.status
//log.debug "wills logging call "
println("call the direct:start route via the service")
Hello service = ctx.getBean("helloService")
def result = service.say("William")
println "service returned : $result "
println "sleep 5 seconds "
sleep (5000)
println "stop camel context"
camelContext.stop()
println "camelCtx state now is : " + camelContext.status
}
}
}
That proxy is just registered as a simple bean like this in the spring context
package com.softwood.services
/**
* Created by willw on 07/06/2017.
*/
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate
import org.springframework.stereotype.Component;
import java.util.concurrent.ExecutionException
#Component
public class HelloImpl implements Hello {
#Produce(uri = "direct:in") /* ?block=true */
private ProducerTemplate template
#Override
public String say(String value) throws ExecutionException, InterruptedException {
assert template
println "def endpoint is : " + template.getDefaultEndpoint()
//Future future = template.asyncSendBody(template.getDefaultEndpoint(), value)
//return future.get()
return template.sendBody (template.getDefaultEndpoint(), value)
}
}
The TimedRoute just sorts itself out with no template required to invoke in
package com.softwood.camelRoutes
/**
* Created by willw on 07/06/2017.
*/
import org.apache.camel.builder.RouteBuilder
import org.springframework.stereotype.Component
#Component
class TimedRoute extends RouteBuilder {
#Override
void configure () throws Exception {
from ("timer:foo")
.to ("log:com.softwood.application.Application?level=WARN")
}
}
My simple no-op file route isn't working (yet) and not sure why. I suspect I've not got the file config right somehow; some playing is required.
package com.softwood.camelRoutes
import org.apache.camel.builder.RouteBuilder
import org.springframework.stereotype.Component
/**
* Created by willw on 08/06/2017.
*/
#Component
class FileNoOpRoute extends RouteBuilder{
#Override
void configure () throws Exception {
from ("file:../com.softwood.file-inbox?recursive=true&noop=true&idempotent=true")
.to ("file:../com.softwood.file-outbox")
}
}
However the basics are not working and least camel is doing something whereas before I just had the exception and nothing.
I have found another question on Spring config highlighting some of the above also.

Resources