Spring Resful Client with RestTemplate - spring

I'm using RestTemplate class to get All user but when i run Main in Client then occur error, i don't know why ???
Exception in thread "main" java.lang.ClassCastException:
java.util.LinkedHashMap cannot be cast to
edu.java.spring.service.user.model.User at
edu.java.spring.service.client.RestClientTest.main(RestClientTest.java:33)
Here file RestClientTest.java
public class RestClientTest {
public static void main(String[] args) throws IOException{
List<User> users = getUsers();
for (int i = 0; i < users.size(); i++) {
System.out.println("Rest Response" + loadUser(users.get(i).getUserName()));
}
}
public static List<User> getUsers(){
String uri = new String("http://localhost:8080/rest/user/list");
RestTemplate rt = new RestTemplate();
return (List<User>) rt.getForObject(uri,List.class);
}
public static String loadUser(String username) throws IOException {
String url = "http://localhost:8080/rest/user/json/" + username;
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
InputStream stream = con.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
Here file UserRestServiceController.java
#Controller
public class UserRestServiceController {
#Autowired
public UserDao userDao;
#Autowired
public View jsonTemplate;
#RequestMapping(value = "/rest/user/list", produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET)
public #ResponseBody List<User> getUsers(){
return userDao.listUsers();
}
#RequestMapping(value="/rest/user/json/{username}")
public ModelAndView loadUser(#PathVariable("username")String name){
return new ModelAndView(jsonTemplate,"data",userDao.loadUser(name));
}

I believe the following method is not returning as you expect:
rt.getForObject(uri,List.class);
Take a look at this question as it might help you also fix your error.
ClassCastException: RestTemplate returning List instead of List

Related

MockWebServer BasicAuth with Spring

I need to do tests by calling an external API, where I do the following:
Service Class:
public class BatchStatusClient {
#Value("${batchStatusUpdate.username}")
private String username;
#Value("${batchStatusUpdate.password}")
private String password;
public BatchStatusClient(#Value("${batchStatusUpdate.endpoint}")
String urlBatchStatusUpdate) {
this.webClient = WebClient.create("urlBatchStatusUpdate");
}
public Mono<JsonNode> getToken(String uuid) {
return this.webClient.post()
.uri("/authorization")
.headers(httpHeaders1 -> {
httpHeaders1.setBasicAuth(username, password);
httpHeaders1.add(REQUEST_ALLOW_ORIGIN, "*");
httpHeaders1.add(REQUEST_ALLOW_CREDENTIALS, "false");
httpHeaders1.add(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE);
})
.body(BodyInserters.fromFormData("grant_type", grantType))
.retrieve()
.bodyToMono(JsonNode.class);
}
}
Test Class:
#TestPropertySource(locations = "classpath:/application-dev.yml")
#SpringBootTest()
#ExtendWith(SpringExtension.class)
#ActiveProfiles("dev")
#ContextConfiguration(classes = BatchStatusClient.class)
public class BatchStatusClientTest {
private BatchStatusClient batchStatusClient;
private static MockWebServer mockWebServer;
#BeforeEach
public void setup() throws IOException {
mockWebServer = new MockWebServer();
mockWebServer.start(9090);
this.batchStatusClient = new BatchStatusClient(
mockWebServer.url("/").toString());
}
#AfterAll
static void tearDown() throws IOException {
mockWebServer.shutdown();
}
#Test
public void test_getToken() throws Exception {
String jsonString = "{\"access_token\": \"QB7VGhGtQWEXB3J98lIjF3\"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jn = mapper.readTree(jsonString);
mockWebServer.enqueue(new MockResponse()
.setBody(new ObjectMapper().writeValueAsString(jn))
.addHeader(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE));
Mono<JsonNode> result = batchStatusClient.getToken("123");
System.out.println("result = " + result);
assertEquals("QB7VGhGtQWEXB3J98lIjF",
result.block().get("access_token").asText());
}
}
But when I run the test I have the following exception:
java.lang.IllegalArgumentException: Username must not be null
at org.springframework.util.Assert.notNull(Assert.java:201)
at org.springframework.http.HttpHeaders.encodeBasicAuth(HttpHeaders.java:1834)
at org.springframework.http.HttpHeaders.setBasicAuth(HttpHeaders.java:770)
at org.springframework.http.HttpHeaders.setBasicAuth(HttpHeaders.java:751)
Should I do any extra configuration?
With these modifications it worked for me:
BatchStatusClient class:
public BatchStatusClient(#Value("${batchStatusUpdate.endpoint}")
String urlBatchStatusUpdate,
#Value("${batchStatusUpdate.username}") String username,
#Value("${batchStatusUpdate.password}") String password){
this.webClient = WebClient.create(urlBatchStatusUpdate);
this.username = username;
this.password = password;
In setup method:
#BeforeEach
void setup() throws IOException {
this.mockWebServer = new MockWebServer();
this.batchStatusClient = new BatchStatusClient(
mockWebServer.url("/").toString(), "username", "password"
);
}

How to handle response codes in RestTemplate without catching exceptions? [Spring Boot]

I'm sending a response to another web service to create an user. If the user already exists it sends back the 409 response. I'm using RestTemplate like so:
#PostMapping("/todos/{toDoNoteId}/users")
public ResponseEntity <String> postUser(#RequestBody User user, #PathVariable int toDoNoteId, UriComponentsBuilder builder)throws HttpMessageNotReadableException, ParseException{
RestTemplate restTemplate = new RestTemplate();
final String uri = "http://friend:5000/users";
try {
ResponseEntity<String> result = restTemplate.postForEntity(uri, user, String.class);
return result;
}
catch (HttpClientErrorException ex) {
return ResponseEntity.status(ex.getRawStatusCode()).headers(ex.getResponseHeaders())
.body(ex.getResponseBodyAsString());
}
}
While catching an exception somewhat works (in the catch block i can access the status code and body), is there a way to access it without exceptions something similar like this:
#PostMapping("/todos/{toDoNoteId}/users")
public ResponseEntity <String> postUser(#RequestBody User user, #PathVariable int toDoNoteId, UriComponentsBuilder builder)throws HttpMessageNotReadableException, ParseException{
RestTemplate restTemplate = new RestTemplate();
final String uri = "http://friend:5000/users";
ResponseEntity<String> result = restTemplate.postForEntity(uri, user, String.class);
if(result.getStatusCode()=="409"){
// do something
}
else{
// do something else
}
return result;
}
Have you been check the ExceptionHandler? When exception throws, ExceptionHandler handles it.
For example:
#ControllerAdvice()
public class CustomExceptionHandler {
private static final Logger logger = LogManager.getLogger("CustomExceptionHandler");
#ExceptionHandler(YourException.class)
public ResponseEntity handleYourException(HttpServletRequest request, YourException ex) {
return ResponseEntity.ok("");
}
#ExceptionHandler(Exception.class)
public ResponseEntity handleException(HttpServletRequest request, Exception ex) {
logExp("Exception", request, ex);
//return new ResponseEntity<>();
return null;
}
}
You can create your own custom resttemplate and define exception handler. Here is a code snippet.
#Configuration
public class CustomRestTemplate extends RestTemplate {
#Autowired
private CustomErrorHandler customErrorHandler;
#PostConstruct
public void init() {
this.setErrorHandler(customErrorHandler);
}
}
#Component
public class CustomErrorHandler implements ResponseErrorHandler {
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
if(response.getStatusCode() != "409"){
return true;
}else {
return false;
}
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
String responseBody = response.getBody();//Pls read from InputStream and create write into String
JSONObject jsonObj = new JSONObject(result);
JSONArray jsonArray = new JSONArray();
jsonObj.put("status", response.getStatusCode());
jsonObj.put("body", responseBody );
jsonArray.put(jsonObj);
responseString = jsonArray.get(0).toString();
throw new MyException(responseString );
}
}
class MyException throw RuntimeException {
public MyException (String message) {
super(message);
}
}
So, your class will changed to
#PostMapping("/todos/{toDoNoteId}/users")
public ResponseEntity <String> postUser(#RequestBody User user, #PathVariable int toDoNoteId, UriComponentsBuilder builder)throws HttpMessageNotReadableException, ParseException{
CustomRestTemplate restTemplate = new CustomRestTemplate ();
final String uri = "http://friend:5000/users";
ResponseEntity<String> result = restTemplate.postForEntity(uri, user, String.class);
return result
}

How to redirect ftl in spring boot?

I have already created an e mail confirmation in spring boot it is working nicely, and also I created a link when a user click it should say "confirmed"but I did not figure it out how to do that?
E mail sender java class:
#Component
public class EmailSender {
#Autowired
JavaMailSender javaEmailSender;
public void sendEmail(String to, String subject, String text) throws MessagingException {
MimeMessage message = javaEmailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true);
helper.addInline("logo.jpg", new ClassPathResource("./images/logo.jpg"));
javaEmailSender.send(message);
}
}
E mail template Loader:
#Component
public class EmailTemplateLoader {
#Autowired
private Configuration freemakerConfiguration;
public String getEmailBody(String name, String confirmationLink) throws TemplateException {
try {
Template template = freemakerConfiguration.getTemplate("EmailConfirmation.ftl");
Map<String, Object> data = new HashMap<String, Object>();
data.put("name", name);
data.put("confirmationLink", confirmationLink);
return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return "";
}
}
My signup Resource :
#Autowired
private SignupService signupService;
#Autowired
private HttpServletRequest httpServletRequest;
#RequestMapping(value = "user/signup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional(rollbackFor = Exception.class)
public ResponseEntity<?> signup(#RequestBody UserType user) throws SignUpException {
URL requestUrl = null;
try {
requestUrl = new URL(httpServletRequest.getRequestURL().toString());
} catch (MalformedURLException e) {
logger.debug("Malformed Request Url");
}
logger.debug(requestUrl.toString());
signupService.signUp(user, requestUrl.getHost());
return new ResponseEntity<>(HttpStatus.OK);
}
#RequestMapping(value = "user/confirmation", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional(rollbackFor = Exception.class)
public ResponseEntity<?> confirmSignUp(#RequestParam("u") String loginName, #RequestParam("p") String token) {
try {
signupService.emailConfirmation(loginName, token);
return new ResponseEntity<>(HttpStatus.OK);
} catch (SignUpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
So, As I told I can send an email successfully, but I could not sort how I can write confirmation successfully

Throwing Custom Exception with HTTP Response From Spring Validator

I have implemented a custom Validator in Spring which is called inside an overridden Jackson de-serializer. If validation fails, I want the HTTP response code to be a 403 Forbidden as defined in my ControllerAdvice.
However, the response is always 400 Bad Request.
public class InterceptedDeserializer extends StdDeserializer<Object> implements ResolvableDeserializer
{
public InterceptedDeserializer(JsonDeserializer<?> defaultDeserializer)
{
super(Object.class);
this.defaultDeserializer = defaultDeserializer;
}
#Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, My403Exception
{
this.classFieldValidator = ServletUtils.findWebApplicationContext().getBean(ClassFieldValidator.class);
Object deserializedObject = defaultDeserializer.deserialize(jp, ctxt);
Errors errors = new BeanPropertyBindingResult(deserializedObject, deserializedObject.getClass().getName());
classFieldValidator.validate(deserializedObject, errors);
if(errors.hasErrors() || errors.hasFieldErrors()){
throw new My403Exception("No funny business");
}
return deserializedObject;
}
}
#ControllerAdvice
public class ValidationControllerAdvice {
private static final Logger log = LoggerFactory.getLogger(ValidationControllerAdvice.class);
private final StringWriter sw = new StringWriter();
#ResponseBody
#ExceptionHandler(My403Exception.class)
#ResponseStatus(HttpStatus.FORBIDDEN)
public ErrorResponse my403Exception(My403Exception e) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setErrorCode("my403");
errorResponse.setDescription(e.getMessage());
errorResponse.setMessage(e.getMessage());
e.printStackTrace(new PrintWriter(sw));
String eStackTrace = sw.toString();
log.error("My403 error message: " + e.getMessage() + "\nException Class:" + e.getClass() + "\nStack Trace:" + eStackTrace);
return errorResponse;
}
}
#ResponseStatus(value = HttpStatus.FORBIDDEN)
public class My403Exception extends RuntimeException{
private String message;
public My403Exception(String message) {
super(message);
this.message = message;
}
public My403Exception() {
}
#Override
public String getMessage() {
return message;
}
}
#ResponseStatus(HttpStatus.CREATED)
#RequestMapping(method = RequestMethod.POST, path = "/thing")
public void createmyThing(#RequestParam(value = "thing") String thing, #RequestBody() #Valid MyThing thing) throws My403Exception {
thingService.createThing(thing);
}

java.io.IOException With Restful Web Service

I have a weird problem with my project. When i run main method in Client to create a User after send to Server then occur fllowing error:
Exception in thread "main" java.io.IOException: Server returned HTTP
response code: 400 for URL: http://localhost:8080/rest/user/create at
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown
Source) at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown
Source) at
edu.java.spring.service.client.RestClientTest.createUser(RestClientTest.java:72)
at
edu.java.spring.service.client.RestClientTest.main(RestClientTest.java:30)
Here file RestClientTest.java
public class RestClientTest {
public static void main(String[] args) throws IOException{
// System.out.println("Rest Response" + loadUser("quypham"));
User user = new User();
user.setUserName("datpham");
user.setPassWord("12345");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,1960);
user.setBirthDay(calendar.getTime());
user.setAge(12);
createUser(user);
System.out.println("Rest Response" + loadUser("datpham"));
}
public static String createUser(User user) throws IOException{
URL url = new URL("http://localhost:8080/rest/user/create");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("POST");
httpConnection.addRequestProperty("Content-Type","application/json");
httpConnection.addRequestProperty("Accept","application/json");
httpConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(httpConnection.getOutputStream());
ObjectMapper mapper = new ObjectMapper();
StringWriter writer = new StringWriter();
mapper.writeValue(writer,user);
wr.writeBytes(writer.getBuffer().toString());
wr.flush();
wr.close();
return readInputStream(httpConnection.getInputStream());
}
public static String readInputStream(InputStream stream) throws IOException{
StringWriter writer = new StringWriter();
try {
int read;
byte[] bytes = new byte[4*1024];
while ((read = stream.read(bytes))!=-1) {
writer.write(new String(bytes,0,read));
}
} finally {
// TODO: handle finally clause
stream.close();
writer.close();
}
return writer.getBuffer().toString();
}
Here file UserRestServiceController.java
#Controller
public class UserRestServiceController {
#Autowired
public UserDao userDao;
#RequestMapping(value = "/rest/user/create",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.CREATED)
public void addUser(#RequestBody User user){
userDao.save(user);
}

Resources