I keep running into an issue and I can't seem to find the solution anywhere. I have an api that responds with an object EmployeeAuthenticatedResponse. This is a single object that has the user's info like his name and roles inside of it. There can only be 1 response and so it will always send 1.
This is the code in the controller of the rest api:
@GetMapping("/authenticate")
public EmployeeAuthenticatedResponse getAuthenticated(@RequestHeader(value = "email") String requestMail, @RequestHeader(value = "password") String requestPassword){
return employeeService.signin(requestMail, requestPassword);
}
This is what I use to try and retrieve it:
public class LoginController {
@FXML
private Label errorText;
@FXML
private TextField email;
@FXML
private PasswordField password;
@FXML
protected void login(ActionEvent event) throws NoSuchAlgorithmException {
if(email != null && email.getText() != "" && password != null && password.getText() != ""){
//Hash password before sending it out(This is just extra for during the connection, the server hashed it again with Bcrypt)
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(password.getText().getBytes(StandardCharsets.UTF_8));
String passwordHash = String.format("%064x", new BigInteger(1,digest));
//Initiate Spring stuff
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//maak headers
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("user-agent", "My app");
headers.add("email", email.getText());
headers.add("password", passwordHash);
HttpEntity<?> entity = new HttpEntity<Object>("parameters", headers);
//Send it away and retrieve
ResponseEntity<EmployeeAuthenticatedResponse> loginResponse = restTemplate.exchange("http://localhost:8080/employee/authenticate", HttpMethod.GET, entity, EmployeeAuthenticatedResponse.class);
//If else stuffs
if(loginResponse.getStatusCode() == HttpStatus.OK){
errorText.setText("it works");
} else if(loginResponse.getStatusCode() == HttpStatus.FORBIDDEN) {
errorText.setText("wrong password");
} else if(loginResponse.getStatusCode() == HttpStatus.REQUEST_TIMEOUT){
errorText.setText("error");
}
}
}
}
Now when I try to use this I get some warnings and an error. First "warning"
18:04:56.170 [JavaFX Application Thread] WARN org.springframework.http.converter.json.MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class link.to.class.DTO.EmployeeAuthenticatedResponse]]
java.lang.reflect.InaccessibleObjectException: Unable to make public link.to.class.EmployeeAuthenticatedResponse() accessible: module link.to.class does not "exports link.to.class.DTO" to unnamed module @13f33d2d
It then gives some extra info:
18:04:56.171 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Accept=[]
18:04:56.173 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Writing [parameters] as "application/json"
18:04:56.683 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK
And then it gives the same failed to evaluate Jackson Deserialization for type warning twice, then I get a Could not extract response: no suitable HttpMessageConverter found for response type error/exception, which is where it ends.
I have looked up a lot around Stack overflow and other sites, when I add [] behind EmployeeAuthenticatedResponse like:
ResponseEntity<EmployeeAuthenticatedResponse[]> loginResponse = restTemplate.exchange("http://localhost:8080/employee/authenticate", HttpMethod.GET, entity, EmployeeAuthenticatedResponse[].class);
I go straight to the exception without the warnings. This makes me think that the issue is that I need to have a list as a response and not a single object when using RestTemplate like this, but then how do I get a single entity? Everything I can find online is about consuming lists.
EmployeeAuthenticatedResponse class:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class EmployeeAuthenticatedResponse {
private int employeeId;
private String employeeFirstName;
private String employeeLastName;
private int employeeDarkMode;
private int employeeRoleId;
private String employeeRoleName;
private int employeePermissionSales;
private int employeePermissionSending;
private int employeePermissionManager;
private int employeePermissionProductManagement;
private String JWTToken;
//Getters and setters
}
The Json:
{
"employeeId": 1,
"employeeFirstName": "TestFname",
"employeeLastName": "TestLname",
"employeeDarkMode": 1,
"employeeRoleId": 1,
"employeeRoleName": "owner",
"employeePermissionSales": 1,
"employeePermissionSending": 1,
"employeePermissionManager": 1,
"employeePermissionProductManagement": 1,
"jwttoken": "JWTTOKEN"
}
Module-info.java:
module com.windsoftware.kassa.windkassadesktop {
requires javafx.controls;
requires javafx.fxml;
requires javafx.web;
requires org.controlsfx.controls;
requires com.dlsc.formsfx;
requires validatorfx;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.bootstrapfx.core;
requires eu.hansolo.tilesfx;
requires spring.boot;
requires spring.web;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.annotation;
requires spring.boot.autoconfigure;
opens link.to.class to javafx.fxml;
exports link.to.class;
exports link.to.class.controllers;
opens link.to.class.controllers to javafx.fxml;
}
Since you are using Java 16, you have to export your DTO package inside your module setup in order for the jackson object mapper inside the rest template to have access to your DTO class and its fields for reflection
Module-info.java:
module com.windsoftware.kassa.windkassadesktop {
requires javafx.controls;
requires javafx.fxml;
requires javafx.web;
requires org.controlsfx.controls;
requires com.dlsc.formsfx;
requires validatorfx;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.bootstrapfx.core;
requires eu.hansolo.tilesfx;
requires spring.boot;
requires spring.web;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.annotation;
requires spring.boot.autoconfigure;
opens link.to.class to javafx.fxml;
exports link.to.class;
exports link.to.class.controllers;
exports link.to.class.DTO;
opens link.to.class.controllers to javafx.fxml;
}