400 Bad Request when uploading byte[] with Spring RestTemplate to SpringMVC rest endpoint - spring

I am trying to upload a byte[] that contains an image to my Spring rest service (running in Spring Boot, btw) as a MultipartFile with my client running Spring RestTemplate and am getting HttpClientErrorException: 400 Bad Request.
My endpoint:
#RequestMapping(value="/scale/{percent}", method= RequestMethod.POST)
public ResponseEntity scaleImage(#PathVariable("percent") float percent,
#RequestParam("file") MultipartFile file) {
try {
if (!file.isEmpty()) {
byte [] result = transformService.scaleImage(percent, file.getBytes());
return getResponseEntityFromBytes(result);
} else {
return generateBadRequestError();
}
} catch (Exception e) {
if (e instanceof InvalidOperationParameterException) {
// TODO - populate message with bad parameters
LOGGER.log(Level.FINE, "Invalid Parameters: ");
return generateBadRequestError();
} else {
LOGGER.log(Level.SEVERE, "Exception caught: " + e.getMessage(), e);
return generateServerError(e.getMessage());
}
}
}
My Spring RestTemplate client:
public void scaleImage(byte[] image, float percent) throws Exception {
String url = "http://localhost:8080/scale/" + percent;
this.testNumberThreads=10;
this.testNumberThreads=10;
MultiValueMap<String, Object> mvm = new LinkedMultiValueMap<>();
mvm.add("file", image);
TransformedResponse r = doPost(url, mvm);
}
private TransformedResponse doPost(String url, MultiValueMap<String, Object> mvm) {
RestTemplate restTemplate = new RestTemplate();
TransformedResponse xr = null;
try {
xr = restTemplate.postForObject(url, mvm, TransformedResponse.class);
} catch (RestClientException e) {
e.printStackTrace();
}
return xr;
}
...
public class TransformedResponse {
byte[] image;
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
}
Here is the exception I'm seeing in the client (nothing hitting server yet):
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:588)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:546)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:502)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:330)
at com.me.image.xform.LoadTest.doPost(LoadTest.java:110)
at com.me.image.xform.LoadTest.loadTestScalePercent(LoadTest.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
Why won't this request post correctly?

I found my problem. I needed to add an AbstractResource (in this case a ByteArrayResource) to my MultiValueMap instead of the raw byte array. Here's the code that fixed it:
public void scaleImage(byte[] image, float percent) throws Exception {
String url = "http://localhost:8080/scale/" + percent;
final byte[] rawBytes = image.clone();
MultiValueMap<String, Object> mvm = new LinkedMultiValueMap<>();
ByteArrayResource bar = new ByteArrayResource(rawBytes) {
#Override
public String getFilename() {
return "Test-"+rawBytes.length + ".jpg";
}
};
mvm.add("file", bar);
TransformedResponse r = doPost(url, mvm);
}

First of all, when using Spring, make sure that you have proper MultiPartFile resolver defined in your servlet context:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="52428800"/>
<property name="maxInMemorySize" value="52428800"/>
</bean>
If you're using maven, this resolver is located in spring-web artifact:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${your.spring.version}</version>
</dependency>
Then, create form and make sure you're using proper enctype:
<form method="post" action="upload.form" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit"/>
</form>
Finally, handle file upload in your controller
#RequestMapping(value="/path", method= RequestMethod.POST)
public StringscaleImage(#RequestParam("file") MultipartFile file) {
//....
}
Remember that asynch file upload is supported only with HTML5, with others you'd need to use some workarounds (like flash or iframes).
If you're still facing 400 Error, add to your logging service this logger (or similar, depending on logging framework):
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p [%c] %m%n"/>
</layout>
</appender>
<logger name="org.springframework.web.method.HandlerMethod">
<level value="TRACE"/>
</logger>
<root>
<priority value="info"/>
<appender-ref ref="console"/>
</root>
It should output exception thrown during request handling

Instead of trying to pass the MultipartFile in as a request parameter, try the following:
#RequestMapping(value="/scale/{percent}", method= RequestMethod.POST)
public ResponseEntity scaleImage(#PathVariable("percent") float percent,
MultipartHttpServletRequest request) {
Iterator<String> fileNames = request.getFileNames();
MultipartFile uploadedFile = request.getFile(fileNames.next());
String fileName = uploadedFile.getName();
This is the only way I could actually get my multipart file to be accepted.
If you are still getting an empty file from this process, it must be something to do with how you are POST'ing the data.

Related

from andriod i am trying to upload image and i am using web services in java

below is the android part
new MultipartUploadRequest(this,uploadid,UPLOAD_URL)
.addFileToUpload(path,"image")
.addParameter("name",name)
.setNotificationConfig(new UploadNotificationConfig())
.setMaxRetries(2)
.startUpload();
below is my java controller in web services
#RequestMapping(value = "/uploadm",method=RequestMethod.POST)
public void submitQuestionuploading(#RequestBody String image) throws Exception
{
System.out.println(1+""+image);
try {
byte[] bytes = image.getBytes();
System.out.println(11);
BufferedOutputStream stream =new BufferedOutputStream(new
FileOutputStream(new File(UPLOAD_DIRECTORY +"11.png")));
stream.write(bytes);
stream.flush();
stream.close();
}
catch (Exception e) {
System.out.println(e);
}
output is this one i got in console but file is created but it is corrupted and it s size 0bytes ,
---------AndroidUploadService1518510071115 Content-Disposition: form-data; name="image"; filename="IMG_20180211_000033.jpg"
Content-Type: image/jpeg
ÿØÿá3ØExif
i tried to put this in java controller but it is not working
#RequestMapping(value = "/upload", method = RequestMethod.POST ,
headers = "Content-Type=multipart/form-data") public String
fileUpload(#RequestParam("image") CommonsMultipartFile file) {}
but i want to do in spring MVC only, help me to take uploaded file
This is a working file uploader
#ResponseStatus(code = HttpStatus.CREATED)
#RequestMapping(value = "asset", method = RequestMethod.POST, consumes = {
MediaType.MULTIPART_FORM_DATA_VALUE}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#ResponseBody
public String uploadImage(
#RequestParam("image") MultipartFile file) {
byte[] bytes = file.getBytes();
//do something with byte
return "ok or anything you want to return";
}
And also you need to register MultipartResolver as a depandency.
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
you can deploy this code and then test using postman.
there are various tutorials for this.
you may have a look at
http://www.baeldung.com/spring-file-upload
https://www.boraji.com/spring-4-mvc-file-upload-example-with-commons-fileupload

#CacheEvict is not working in SpringBoot

#Cacheable(value = "apis", key = "#request")
public Object queryCenterAPI(QCRequest request,HttpHeaders headers) throws JSONException, ParseException {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new ToolsResponseHandler());
Response res=new Response();
HashMap<String,String> map=new HashMap<String,String>();
logger.info("No Caching^^^^^^^^^^");
Gson gson = new Gson();
String requestJson = gson.toJson(request);
HttpEntity<String> requestEntity = new HttpEntity<String>(requestJson, headers);
System.out.println("Request Body "+requestEntity);
Object response = null;
try {
response = restTemplate.postForObject(QCUtils.queryURL, requestEntity, Object.class);
logger.info("1st response>"+response);
response = response.toString().replaceAll("\\\\", "");
System.out.println("Final response "+response);
}catch (HttpClientErrorException httpEx) {
logger.info("Error:"+httpEx);
}
return response;
}
#CacheEvict(value = "apis", key = "#request")
public void resetOnRequest(QCRequest request) {
// Intentionally blank
System.out.println("Evict in Progrsss......");
}
Caching is working fine but I am unable to use #CacheEvict annotation.I guess cacheEvict method is called immediately after Cacheable method.
The resetOnRequest() method is not called after Cachable method(queryCenterAPI).
Cache evict method should be called from a different class otherwise it will not work, same for method with #Cacheable annotation.
Another different way instead the #CacheEvict annotation, would be using the CacheManager > https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/CacheManager.html
For single value;
public void evictSingleCacheValue(String cacheName, String cacheKey) {
cacheManager.getCache(cacheName).evict(cacheKey);
}
For all values;
public void evictAllCacheValues(String cacheName) {
cacheManager.getCache(cacheName).clear();
}
Using ehcache works for me andAdding the below Xml file and Config file is enough to do caching and cache evict.
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="apis"
eternal="false"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="200" timeToLiveSeconds="900"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
</cache>
public class AppConfig {
#Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
#Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
return cmfb;
}
}
We only need to configure in xml file and give the time after which cache eviction take place.
I think you will need to switch to the "aspectj" mode in order for the #CacheEvict to work fine.
From Spring documentation:
The default advice mode for processing caching annotations is "proxy"
which allows for interception of calls through the proxy only; local
calls within the same class cannot get intercepted that way. For a
more advanced mode of interception, consider switching to "aspectj"
mode in combination with compile-time or load-time weaving.
Second option would be to try to move the #CacheEvict method into another class.

How to pass object/json to post method using int-http:outbound-gateway in Spring Integration

How we can pass an object or json from Activator to int-http:outbound-gateway.
Below are my configs
<int:channel id="preparedData"/>
<int:service-activator input-channel="preparedData" ref="writer" method="writeData" output-channel="CallbackChannel">
</int:service-activator>
<int:channel id="CallbackChannel" />
<int-http:outbound-gateway
request-channel="CallbackChannel"
http-method="POST" url="{url}"
extract-request-payload="true">
<int-http:uri-variable name="url" expression="headers['url']" />
</int-http:outbound-gateway>
And my activator is returning one Object which is being expected in the POST API in one controller in #RequestBody
With above config getting below error.
13:58:41.202 [task-scheduler-1] ERROR org.springframework.integration.handler.LoggingHandler - org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [http://**myUrl**]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
Kindly suggest.
EDIT1
If I am converting my returned MyObject in JSON format in Activator then I am getting below error.
nested exception is java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
Edit 2
When I changed my returntype of my Activator to Map with one of key value pair as 'input' and Object then it complains as below.
HTTP request execution failed for URI [http://MYURL]; nested exception is java.lang.ClassCastException: com.******.MyObject cannot be cast to java.lang.String
The <int-http:outbound-gateway> delegates all the hard work to the RestTemplate, which comes with this set of HttpMessageConverters by default:
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter<>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
}
else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
}
if (jackson2SmilePresent) {
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
}
if (jackson2CborPresent) {
this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
}
I think your Object is converted somehow to the wire bytes, you only should be sure that the proper and appropriate converted is used. And that is really depends of the server (#RequestBody) requirements.
Below is my solution that worked.
<int:channel id="preparedData"/>
<int:service-activator input-channel="preparedData" ref="writer" method="writeData" output-channel="CallbackChannel"/>
<int:channel id="CallbackChannel"/>
<int:transformer input-channel="CallbackChannel"
output-channel="registrationQueue"
ref="transformer" method="doTransform"/>
<int:channel id="registrationQueue" />
<int:header-enricher input-channel="registrationQueue" output-channel="enricherOutput">
<int:header name="contentType" value="application/json"/>
</int:header-enricher>
<int:channel id="enricherOutput" />
<int-http:outbound-gateway
request-channel="enricherOutput"
http-method="POST" url="{url}"
extract-request-payload="true"
reply-channel="replyChannel"
message-converters="converter"
<int-http:uri-variable name="url" expression="headers['url']" />
</int-http:outbound-gateway>
<util:list id="converter">
<bean id="test" class="com.xx.rr.ttt.MyMessageConvertor" />
</util:list>
<int:channel id="replyChannel" />
<int:service-activator input-channel="replyChannel" ref="lastActivator"/>
Had to add converter with below code.
public class MyMessageConvertor extends AbstractHttpMessageConverter<MyMessageConvertor> {
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
public MyMessageConvertor() {
this(DEFAULT_CHARSET);
}
public MyMessageConvertor(Charset defaultCharset) {
super(defaultCharset, new MediaType("application", "json"), MediaType.ALL);
}
#Override
protected boolean supports(Class<?> clazz) {
return true;
}
#Override
protected MyResponse readInternal(Class<? extends MyResponse > clazz,
HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
#Override
protected void writeInternal(MyResponse t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
ObjectMapper mapperObj = new ObjectMapper();
String jsonStr = null;
try {
jsonStr = mapperObj.writeValueAsString(t);
} catch (IOException e) {
e.printStackTrace();
}
Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType());
StreamUtils.copy(jsonStr, charset, outputMessage.getBody());
//System.out.println("outputMessage.getBody()" + outputMessage.getBody());
}
private Charset getContentTypeCharset(MediaType contentType) {
if (contentType != null && contentType.getCharset() != null) {
return contentType.getCharset();
}
else {
return getDefaultCharset();
}
}
}
I did not implement readInternal because the url that I am hitting is not returning anything but reply-channel in http:outbound-gateway is mandatory attribute thtswhy I had to add one and add one more activator which is finishing the flow.

Response Error 500 in Spring (HttpStatus field null pointer)

I have build a rest web service using spring. I am getting 500 server error when the service is called.
Controller class :
#RequestMapping(value = "/wordlist", method = RequestMethod.GET)
public ResponseEntity getList(#RequestHeader("wordid") int wordId) {
ResponseList responseObejct = wordService.getList(wordId);
return ResponseEntity.status(responseObejct.getStatusCode()).body(responseObejct.getResponseWordList());
}
DaoImplementation :
String listHql = "from Word where wordId > ? or wordId = ?";
Query query = session.createQuery(listHql);
query.setParameter(0, wordId);
query.setParameter(1, wordId);
query.setMaxResults(30);
if(query.list().size()>0){
response.setStatusCode(HttpStatus.OK);
response.setResponseWordList((ArrayList<Word>)query.list());
} else {
response.setStatusCode(HttpStatus.NOT_FOUND);
}
session.getTransaction().commit();
ResponseList.java (for response)
public class ResponseList {
private ArrayList<Word> responseWordList;
private HttpStatus statusCode ;
public ArrayList<Word> getResponseWordList() {
return responseWordList;
}
public void setResponseWordList(ArrayList<Word> responseWordList) {
this.responseWordList = responseWordList;
}
public HttpStatus getStatusCode() {
return statusCode;
}
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
}
Error is:
ava.lang.IllegalArgumentException: Can not set final org.springframework.http.HttpStatus field
org.springframework.http.ResponseEntity.statusCode to java.util.ArrayList
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
java.lang.reflect.Field.get(Field.java:393)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:86)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
com.google.gson.Gson.toJson(Gson.java:586)
com.google.gson.Gson.toJson(Gson.java:565)
org.springframework.http.converter.json.GsonHttpMessageConverter.writeInternal(GsonHttpMessageConverter.java:199)
org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:222)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
I cannot understand why the error is coming. Please help.
The way you are calling ResponseEntity.status() is not valid.
It says
The method status(HttpStatus) is undefined for the type
ResponseEntity
To fix this try returning a ResponseEntity from your controller method like :
#RequestMapping(value = "/wordlist", method = RequestMethod.GET)
public ResponseEntity<ResponseList> getList(#RequestHeader("wordid") int wordId) {
ResponseList responseObejct = wordService.getList(wordId);
ResponseEntity<ResponseList> responseEntity = new ResponseEntity<>(responseObejct, HttpStatus.OK);
return responseEntity;
}
I ran into the same issue, and it turned out that this was fixed in Spring 4.3.1.
However, I cannot find a JIRA issue for that. Maybe it is a side-effect on another fix.
If you still have the problem (or if anyone else steps into this), please try again with 4.3.1 or higher.

hecache is always returning the same result

I'm developing a web service system. I'm using Spring framework and hecache.
the problem is that when i do my first request to the URL I get the correct result but when I do a second request with another parameter it still returning the same result as the first request. When the cache expires it returns the correct result the first time.
This is my Spring Service method
#Cacheable(value="getUserInformation", key="#progid")
public Object getUserInformation(String login, String progid, HttpServletRequest request){
System.out.println( login.concat(progid) );
try {
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).
withCatalogName("siv_pck_general_functions").
withFunctionName("fn_get_user_information");
SqlParameterSource out = new MapSqlParameterSource().addValue("p_loginname", login).addValue("p_programid", progid);
map.put("Result", simpleJdbcCall.executeFunction(List.class, out) );
logger.info( LogUtils.getTypeMessage(request.getRemoteAddr(), request.getRequestURI(), LogUtils.INFO ));
} catch (Exception e) {
map.put("Result","Error");
}
return map;
}
This is my ecache configuration
<cache name="getUserInformation"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
This is my Web Service mapping
#RequestMapping( value="/getUserInformation/{loginName}/{programId}/{token}", method = RequestMethod.GET, produces="application/json;charset=UTF-8" )
public Object getUserInformation( #PathVariable String loginName, #PathVariable String programId, #PathVariable String token,HttpServletRequest request){
httpServletRequest = request;
String result = validateToken(token);
if ( "OK".equals(result) ){
map.put("Result", service.getUserInformation(loginName, programId, request) );
}else{
map.put("Result",result);
}
return map;
}

Resources