File upload, communication between two spring boot application - spring

I have two spring boot application, one is 'AngularApp' (localhost:8870) supporting my front and the other one is 'batchApp'(localhost:8871) running some batches.
I would like to upload a file from my 'Front' to 'AngularApp', then to 'batchApp' as illustrated below.
Right now I did the upload from 'Front' to 'AngularApp', basically using REST API with one controller and service in 'AngularApp'.
#PostMapping("/post")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file)
It works well and upload the file into a specific folder 'upload-dir'.
Now I want 'AngularApp' and 'batchApp' to communicate so 'AngularApp' can give him the file uploaded, but I have no idea about how to do it. REST API ? Any ideas?

For the better approach to solve this problem using spring-framework libraries, please refer
https://piotrminkowski.wordpress.com/2017/02/05/part-1-creating-microservice-using-spring-cloud-eureka-and-zuul/
Below spring framework components make it easy.
Zuul – gateway service that provides dynamic routing, monitoring, resiliency, security, and more
Ribbon – client side load balancer
Feign – declarative REST client
Eureka – service registration and discovery
Sleuth – distributed tracing via logs
Zipkin – distributed tracing system with request visualization.

Here you'll find my working solution, with pvpkiran advice and following this method multipart upload with HttpClient4 :
In AngularApp, http post request :
public void batchAppUploadFile(String fileName) {
log.i("Creating HTTP POST Request to upload a file on batchApp server");
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(myFile_URL);
File file = new File(Paths.get("upload-dir").resolve(fileName).toString());
FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", fileBody);
HttpEntity entity = builder.build();
post.setEntity(entity);
log.i("Executing HTTP Request...");
try {
HttpResponse response = client.execute(post);
log.i("The request went well !");
ResponseEntity.status(HttpStatus.OK).body("SUCESS BS upload");
} catch (Exception e) {
log.i("The request failed !");
ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("FAIL BS upload");
}
}
My controller in batchApp :
#PostMapping("/uploadfile")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file) {
try {
Path uploadPath = Paths.get(getUploadDirectory(file));
Files.copy(file.getInputStream(), uploadPath.resolve(file.getOriginalFilename()));
log.i(file.getOriginalFilename() + " upload complete !");
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
return ResponseEntity.status(HttpStatus.OK).body("Uploaded on batchApp");
}

Related

How do you get the Request URL in spring Boot from an AuthorizationFailureEvent

We are using Spring Boot 2.5.2 with Keycloak 14.0. I am trying to log the authorization events in addition to the URL the user called.
I am trying to follow Spring Boot Authentication Auditing Support. The code to retrieve the Request URL is:
private void onAuthorizationFailureEvent(
AuthorizationFailureEvent event) {
Map<String, Object> data = new HashMap<>();
data.put(
"type", event.getAccessDeniedException().getClass().getName());
data.put("message", event.getAccessDeniedException().getMessage());
data.put(
"requestUrl", ((FilterInvocation)event.getSource()).getRequestUrl() );
if (event.getAuthentication().getDetails() != null) {
data.put("details",
event.getAuthentication().getDetails());
}
publish(new AuditEvent(event.getAuthentication().getName(),
AUTHORIZATION_FAILURE, data));
}
When I attempt this I am getting a ClassCastException when calling event.getSource(). The source seems to be a ReflectiveMethodInvocation (to my Controller) and not a FilterInvocation. Can anybody explain this? How do I get the request url?

API Authentication in Spring Boot

I am building a Spring Boot service that is supposed to call to an external API, and then send the fetched data to the client-side. To send any requests, I must first authenticate by sending a POST request with specific data in the request body, which then sends back a response with authentication key as a cookie. I've made it work in Postman but don't know how to do this in Spring Boot.
I would recommend to have something similar to this:
The main ideea is to use a rest template.
RestTemplate restTemplate = new RestTemplate();
HttpEntity entity = new HttpEntity<String>(headers);
try {
String result = restTemplate.postForEntity(externalAPIUrl, entity, String.class).getBody();
} catch (HttpClientErrorException ex) {
if (ex.getStatusCode() == HttpStatus.BAD_REQUEST) {
}
}

Strange behaviour while runnning spring boot actuator

I am working with a spring boot app which evolve actuator in the pictures .It evolves the endpoint roles.
Below is my controller part which handle the healthStaus
public ModelAndView healthStatus() {
ModelAndView view= new ModelAndView();
final String uri = "http://localhost:8090/actuator";
RestTemplate restTemplate = new RestTemplate();
String response=restTemplate.getForObject(uri,String.class);
try {
Object ob=new ObjectMapper().readValue(response, Employee.class); }
catch (IOException e){
e.printStackTrace();
}
view.addObject("objects",ob);
view.setViewName("dashboard");
return view;
}
while the request handle at this part of code at time of execution it show a strange behaviour .It download a file automatically with the same name of url.

How do I use okhttp in the spring cloud ribbon

The getting started of the spring cloud ribbon is very easy and simple, and it is using the rest template to communicate with backend servers.
But in our project we are more like to use okhttp to do the http request, does anyone can help?
You can take a look at the spring-cloud-square project which supplies integration with Square's OkHttpClient and Netflix Ribbon via Spring Cloud Netflix, on the Github. Let's see a test method in the OkHttpRibbonInterceptorTests.java class
#Test
#SneakyThrows
public void httpClientWorks() {
Request request = new Request.Builder()
// here you use a service id, or virtual hostname
// rather than an actual host:port, ribbon will
// resolve it
.url("http://" + SERVICE_ID + "/hello")
.build();
Response response = builder.build().newCall(request).execute();
Hello hello = new ObjectMapper().readValue(response.body().byteStream(), Hello.class);
assertThat("response was wrong", hello.getValue(), is(equalTo("hello okhttp")));
}

How to manage Feign errors?

We are using Spring-boot with Spring-cloud and Spring-cloud-netflix with Spring-cloud-feign.
We are creating our Gateway application that with the help of Feign will try to communicate with our authentication microservice in order to validate their credentials. Here you can see an example of our Feign authentication client:
#FeignClient(value="auth", configuration = AuthClientConfiguration.class)
public interface AuthClient {
#RequestMapping(method = RequestMethod.GET, value = "/tokens", consumes = MediaType.APPLICATION_JSON_VALUE)
Single<Session> getSession(#RequestHeader("Authorization") String token);
}
The question is, how we can deal with all the exceptions that could be raised by the client? I mean, how we can for example catch that a NetworkException or a TimeoutException has been thrown? We've defined our own ErrorDecoder but it appears that this "kind of listener" only works when the request has arrived and the response returned (in our case from authentication client). So, how we can manage this other exceptions?
Best,
Error decoders are decoding HTTP error responses (500, 404, 401, etc...). Exceptions will bubble up in client calls, so using try/catch should work.
try {
return client.home();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}

Resources