Springboot #Value not loading - spring-boot

In my sample Springboot project on Github, the #Value property won't get loaded when starting the application. I cannot explain the strange behavior and hope that anyone could help me please to solve it and to avoid such stupid errors?
#RestController
public class PostClient {
#Value(value = "${target.uri}")
public String uri;
private RestTemplate restTemplate = new RestTemplate();
private HttpHeaders headers = new HttpHeaders();
public PostClient() {}
public HttpStatus postNumberPlate(CamImage camImage) {
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("numplate", camImage.getIdentifier());
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<LinkedMultiValueMap<String,
Object>>(map, headers);
ByteArrayResource resource = new ByteArrayResource(camImage.getData()) {
#Override
public String getFilename() {
return camImage.getIdentifier() + ".png";
}
};
map.add("image", resource);
System.out.println(uri);
ResponseEntity<String> result = restTemplate.exchange(uri,
HttpMethod.POST,
requestEntity, String.class);
return result.getStatusCode();
}
}
The application.properties
target.uri=http://localhost:9001/postoffice
I read that the #Value is a core functionality of Springboot and should work fine. My project is so small, that I wonder what might broke the framework's behavior of automatic value replacement. I found different and similar questions regarding the #Value issue, but a real explanation cannot be found.
I tried to use a #Component Class with getters/setters and tried to #Autowire it into the shown Class, but that didn't work, too.
I'd like to go the proposed way of the Springboot reference, because any hard-coded String will result in problems, when building docker containers, where I must pass a configuration parameter. So I cannot only rely on a fixed application.properties in the classpath.
EDIT:
Running the application looks like:
shell:>one
Euro Plate # unimportant sysout
CamImage [identifier=BNAYG63, data=[B#4f4c4c4b] # generated plate
null # from sysout here should be the address!!
URI is not absolute
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
shell:>stacktrace
java.lang.IllegalArgumentException: URI is not absolute
at java.base/java.net.URL.fromURI(URL.java:674)
at java.base/java.net.URI.toURL(URI.java:1116)
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:87)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:731)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579)
at dev.semo.npgen.service.PostClient.postNumberPlate(PostClient.java:45)
at dev.semo.npgen.shell.NumberplateClientCommands.one(NumberplateClientCommands.java:62)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.shell.Shell.evaluate(Shell.java:180)
at org.springframework.shell.Shell.run(Shell.java:142)
at org.springframework.shell.jline.InteractiveShellApplicationRunner.run(InteractiveShellApplicationRunner.java:84)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:770)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
at dev.semo.npgen.NpgenApplication.main(NpgenApplication.java:10)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

I have pulled your source from github and tested. Initially it was throwing error as you mentioned. After I have changed like below it is working fine. You should to autowire the PostClient, because the scanning happened and loaded the defaults while you started the application.
#ShellComponent
public class NumberplateClientCommands {
#Autowired
private PostClient postClient;
.....
#ShellMethod("Sends one simple POST request.")
public String one() throws FileNotFoundException {
NumberPlateUtility np = new NumberPlateUtility();
HttpStatus response = postClient.postNumberPlate(np.completeImage());
if (response == HttpStatus.ACCEPTED) {
return "Request sent successfully.";
}
return String.format("Request failed: %s", response.getReasonPhrase());
}
.......
}

Follow this Code Snip
#Value("${target.uri}")
private String uri;

Related

Mockito is returning "java.lang.IllegalArgumentException: URI is not absolute" in RestTemplate.exchange Springboot

Mockito is returning "java.lang.IllegalArgumentException: URI is not absolute" in RestTemplate.exchange. I am not sure why this is happening because it seems I am mocking the restTemplate properly and since I am seeing that exception, it seems that RestTemplate is not a mock.
Here is my class
#Component
public class RestTemplateWrapper {
private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateWrapper.class);
public <T> ResponseEntity<T> callWebServiceGET(String url,HttpEntity<?> httpEntity,
ParameterizedTypeReference<T> parameterizedTypeReference) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<T> response=null;
LOGGER.trace("Entered callWebServiceGET");
LOGGER.info("Calling WebService {}", url);
try {
response=restTemplate.exchange(url, HttpMethod.GET, httpEntity, parameterizedTypeReference);
} catch (HttpClientErrorException e) {
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
LOGGER.error("Service Unavailable - Code 404 returned. " + url + e.getMessage());
} else if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
LOGGER.error("Token Expired- Code 401 returned. " + e.getMessage());
} else if (HttpStatus.BAD_REQUEST.equals(e.getStatusCode())) {
LOGGER.error("Bad Input, 400 returned.{} {} ", url , e.getMessage(), e);
} else {
LOGGER.error("WEB Service Failure. " + e.getMessage());
}
}
return response;
}
}
And here is my TestCase:
#PrepareForTest({RestTemplateWrapper.class})
public class RestTemplateWrapperTest {
#Mock
private RestTemplate mockRestTemplate;
#InjectMocks
private RestTemplateWrapper webUtils;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void callWebServiceGET_OK() {
HttpEntity<String> httpEntity= new ResponseEntity<>(HttpStatus.OK);
ResponseEntity<String> entityResponse=new ResponseEntity<>("MOCK_RESPONSE", HttpStatus.OK);
when(mockRestTemplate.exchange(eq("/objects/get-objectA"), eq(HttpMethod.GET), eq(httpEntity),any(
ParameterizedTypeReference.class))).thenReturn(
entityResponse);
ResponseEntity<String> mockResponse= webUtils.callWebServiceGET("",null, new ParameterizedTypeReference<String>(){
});
//verify(mockRestTemplate,times(1)).exchange(Matchers.anyString(), Matchers.any(), Matchers.any());
Assert.assertEquals("MOCK_RESPONSE",mockResponse.getBody());
}
}
The response:
URI is not absolute
java.lang.IllegalArgumentException: URI is not absolute
at java.net.URI.toURL(URI.java:1088)
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:87)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:727)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:666)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:604)
at com.project.di.tp.purchaseorderservice.utils.RestTemplateWrapper.callWebServiceGET(RestTemplateWrapper.java:29)
at com.project.di.tp.purchaseorderservice.utils.RestTemplateWrapperTest.callWebServiceGET_OK(RestTemplateWrapperTest.java:51)
Any idea about how to solve this issue? I have been trying like 4 hours.
I found the solution, it seems the problem is that my class is RestTemplateWrapper is creating a instance inside callWebServiceGET therefore mockito can`t mock that object. If if set the object outside the method, it works but I dont want to do that.
Is there any way to mock a object that is inside a method?
Although it is not stated explicitly in the JavaDocs it is the case that you have to provide an absolute URL there.
This is because you do nowhere provide a base URL where a relative URL would be relative to. You could not enter "/objects/get-objectA" as URL in your browser either.
So I would suggest that you use something like "http://example.com/objects/get-objectA" instead for the first parameter:
when(mockRestTemplate.exchange(
eq("http://example.com/bla"),
eq(HttpMethod.GET),
isNull(HttpEntity.class),
any(ParameterizedTypeReference.class))).
thenReturn(entityResponse);
ResponseEntity<String> mockResponse =
webUtils.callWebServiceGET(
"http://example.com/bla",
null,
new ParameterizedTypeReference<String>(){});
Please note that the call to webUtils.callWebServiceGET with given parameters would not make Mockito return the wanted answer, so I changed for one the URL in the call to the absolute URL you are expecting in the Mockito.when and also changed the parameter expected there to be a typed null (typed to match the method signature).
UPDATE:
As you found out by yourself already, your Mockito.when doesn't work because you do not use the created mock from the test in your tested method, but instead create a fresh instance of RestTemplate in each call of callWebServiceGET. (Don't know why I didn't see it earlier, sorry!)
I recommend that instead you inject the RestTemplate into the tested class with a constructor:
private final RestTemplate restTemplate;
public RestTemplateWrapper(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
// remove the following line in the method callWebServiceGET:
// RestTemplate restTemplate = new RestTemplate();
With this code, Spring will automatically inject your mocked RestTemplate into the test, but for running the production code you need to add a bean to provide a RestTemplate for injection.
Add this to a Configuration class where you also define other beans:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// Do any additional configuration here
return builder.build();
}
(Found this code snippet in an answer to How to autowire RestTemplate using annotations)
And as a general advice for testing: try to avoid the use of the new operator in any code you want to test, but use injection instead. If you need to create multiple instances (e.g. in a loop, etc.) try to inject a factory that creates the instances for you - so in the test you can mock the factory.

How to do integration tests for endpoints that use ZeroCopyHttpOutputMessage

I have an endpoint that casts the org.springframework.http.server.reactive.ServerHttpResponse to org.springframework.http.ZeroCopyHttpOutputMessage.
#SneakyThrows
#GetMapping("/document/{documentId}")
public Mono<Void> serveDocument(#PathVariable final String documentId, final ServerHttpResponse response) {
final Path documentLocation = fileManipulatorService.newFile(stagingConfigurationProperties.location(), documentId);
return ((ZeroCopyHttpOutputMessage) response)
.writeWith(documentLocation, 0, fileManipulatorService.size(documentLocation))
.then(deleteIfExists(documentLocation));
}
Usually, this works well but when calling the endpoint with org.springframework.test.web.reactive.server.WebTestClient the call fails with the following exception:
2022-12-30T18:49:07.678+01:00 ERROR 1392 --- [ parallel-1] a.w.r.e.AbstractErrorWebExceptionHandler : [1848ca22] 500 Server Error for HTTP GET "/document/11c92bad-6fe4-4c85-9d54-4bf4bbad3581"
java.lang.ClassCastException: class org.springframework.mock.http.server.reactive.MockServerHttpResponse cannot be cast to class org.springframework.http.ZeroCopyHttpOutputMessage (org.springframework.mock.http.server.reactive.MockServerHttpResponse and org.springframework.http.ZeroCopyHttpOutputMessage are in unnamed module of loader 'app')
at com.github.bottomlessarchive.loa.stage.view.document.controller.StageDocumentController.serveDocument(StageDocumentController.java:53) ~[main/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ? HTTP GET "/document/11c92bad-6fe4-4c85-9d54-4bf4bbad3581" [ExceptionHandlingWebHandler]
This is what my test looks like:
#Test
void testServeDocument() {
final UUID documentId = UUID.randomUUID();
final byte[] content = {1, 2, 3, 4};
final Path contentPath = setupFakeFile("/stage/" + documentId, content);
when(fileManipulatorService.newFile("/stage/", documentId.toString()))
.thenReturn(contentPath);
final byte[] responseBody = webTestClient.get()
.uri("/document/" + documentId)
.exchange()
.expectStatus()
.isOk()
.expectBody()
.returnResult()
.getResponseBody();
assertThat(responseBody)
.isEqualTo(content);
assertThat(contentPath)
.doesNotExist();
}
For me, everything seems to be right. Is there a reason why MockServerHttpResponse doesn't extend ZeroCopyHttpOutputMessage? I wanted to file a bug report to Spring Boot because of this, but before doing so, I came to the conclusion that it might be a better idea to ask first on Stackoverflow.
Firstly, MockServerHttpResponse is a general use mock implementation of a response for tests without an actual server, so it's implemented in a way that is just sufficient and convenient for testing.
Secondly, it doesn't look like any guarantees were ever given that a response in a ServerWebExchange must implement ZeroCopyHttpOutputMessage so I wouldn't blindly cast it without prior type checking.
Another caveat, on Netty even if a response is a ZeroCopyHttpOutputMessage, the transfer will use zero-byte copy only when the specified path resolves to a local file system File, and compression and SSL/TLS are not enabled. Otherwise chunked read/write will be used.
( https://projectreactor.io/docs/netty/release/api/reactor/netty/NettyOutbound.html#sendFile-java.nio.file.Path-long-long- ).
Considering all this I'd refactor your controller to something like this:
#SneakyThrows
#GetMapping("/document/{documentId}")
public Mono<Void> serveDocument(#PathVariable final String documentId, final ServerHttpResponse response) {
...
if (response instanceof ZeroCopyHttpOutputMessage zeroCopyHttpOutputMessage) {
return zeroCopyHttpOutputMessage
.writeWith(documentLocation, 0, ...)
...
}
return response
.writeWith(DataBufferUtils.read(documentLocation, response.bufferFactory(), bufferSize))
...
}
To test the ZeroCopyHttpOutputMessage part of this controller in your integration tests you can use a real (non-mocked) web environment and bind your WebTestClient to that like so:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests {
#LocalServerPort
private Integer serverPort;
...
#Test
void testServeDocument() {
WebTestClient webTestClient = WebTestClient
.bindToServer()
.baseUrl("http://localhost:" + serverPort)
.build();
...

LDAP Authentication with Spring - getting PartialResultException

I am following this article on setting LDAP Authentication with Spring
Now I can login to the application, but I get this exception:
Unprocessed Continuation Reference(s); nested exception is javax.naming.PartialResultException:
Unprocessed Continuation Reference(s); remaining name 'DC=XEROX,DC=AD,DC=XEROX,DC=com'
Caused by: javax.naming.PartialResultException: Unprocessed Continuation Reference(s)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2917) ~[na:1.8.0_144]
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2891) ~[na:1.8.0_144]
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1846) ~[na:1.8.0_144]
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769) ~[na:1.8.0_144]
according to other articles I read, I need to set the referral to follow, setReferral("follow");
But I am not sure where to add this to this code:
String completeUrl = new StringBuffer(this.url).append(":")
.append(this.port)
.append("/")
.append(this.contextRoot)
.toString();
auth.ldapAuthentication()
.userSearchFilter(userSearchFilter)
.userDnPatterns(userDnPatterns)
.contextSource()
.url(completeUrl)
.managerDn(managerDn)
.managerPassword(managerPassword);
You should create your own contextSource, something like:
#Bean("internalLdapContextSource")
public LdapContextSource getLdapContextSource() {
String ldapUrl = env.getProperty("ldap.server");
String managerDn = env.getProperty("ldap.manager.distinguished.name");
String managerPassword = env.getProperty("ldap.manager.password");
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(ldapUrl);
contextSource.setUserDn(managerDn);
contextSource.setPassword(managerPassword);
Map<String, Object> baseEnvironmentProperties = new HashMap<>();
baseEnvironmentProperties.put("java.naming.referral", "follow");
contextSource.setBaseEnvironmentProperties(baseEnvironmentProperties);
return contextSource;
}
You can use setBaseEnvironmentProperties method as shown in the sample or setReferral ( both works fine ).
Finally use
.contextSource(getLdapContextSource())

Spring rest template 401 error response

I have a rest controller answering on http://localhost:8080/documents.
I should have an authorization header to call it.
So in my client code i have :
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, "myToken");
HttpEntity entity = new HttpEntity(null, headers);
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
response = restTemplate.exchange("http://localhost:8080/documents", HttpMethod.GET, entity, Document[].class);
Everything works fine.
After that i want to test the errors.
So, i remove the authorization header.
When i test with a tool like postman, i receive the 401 response.
But with my rest template, i only receive an IllegalArgumentException.
I alse have tested the ResponseErrorHandler.
public class MyErrorHandler implements ResponseErrorHandler {
#Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return false; //i've also tried return true
}
#Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
String theString = IOUtils.toString(clientHttpResponse.getBody());
FunctionalTestException exception = new FunctionalTestException();
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("code", clientHttpResponse.getStatusCode().toString());
properties.put("body", theString);
properties.put("header", clientHttpResponse.getHeaders());
exception.setProperties(properties);
throw exception;
}
}
and in my client i have
restTemplate.setErrorHandler(new MyErrorHandler());
It didn't work.
So my question is how to find my 401 error response using the rest template.
Here is the exception :
java.lang.IllegalArgumentException: invalid start or end
and the stack trace :
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1455)
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2979)
java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:489)
org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:84)
org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:619)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498)
org.boite.dq.steps.UnauthorizedUser.callListCategories(UnauthorizedUser.java:61)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.jbehave.core.steps.StepCreator$ParametrisedStep.perform(StepCreator.java:733)
org.jbehave.core.embedder.PerformableTree$FineSoFar.run(PerformableTree.java:346)
org.jbehave.core.embedder.PerformableTree$PerformableSteps.perform(PerformableTree.java:1088)
org.jbehave.core.embedder.PerformableTree$AbstractPerformableScenario.performRestartableSteps(PerformableTree.java:953)
org.jbehave.core.embedder.PerformableTree$NormalPerformableScenario.perform(PerformableTree.java:992)
org.jbehave.core.embedder.PerformableTree$PerformableScenario.perform(PerformableTree.java:902)
org.jbehave.core.embedder.PerformableTree$PerformableStory.performScenarios(PerformableTree.java:825)
org.jbehave.core.embedder.PerformableTree$PerformableStory.perform(PerformableTree.java:798)
org.jbehave.core.embedder.PerformableTree.performCancellable(PerformableTree.java:422)
org.jbehave.core.embedder.PerformableTree.perform(PerformableTree.java:393)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:292)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:266)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
The crash is happening in HttpURLConnection::getHeaderField so I'd suspect that one of your response headers is malformed (not what HttpURLConnection expects it to be). Usually a 401 response comes with a WWW-Authenticate response header pointing the agent to the authentication methods supported by the service. I'd suspect that this header causes the crash.
A bug report in Jersey's issue-tracker shows that HttpURLConnection puts some constraints on the WWW-Authentication header format. In this particular case the value causing a similar crash is oauth_problem=token_rejected. A workaround proposed there is:
Workaround is to send valid header values (spec compliant) or using the ApacheConnector

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.

Resources