Spring boot Rest API internationlization based on request parameter - java

We have a spring boot REST application with APIs having both GET and POST methods.We have few response messages that need to internationalized based on a parameter "locale" for both GET and POST.In case of GET,locale will be passed as query parameter(eg:http://sampleapp/search?locale=en) and for POST method,locale will be part of request JSON. It would be great if I could get some reference implementation for this scenario.

At first I think you do not need to have locale path param. Instead of you can use the standard Accept-Language HTTP header property. You can read about this header here.
This is the way how you can read the accept-language information from the HTTP request in your rest method:
#RequestMapping(produces = "application/json", method = RequestMethod.GET)
public ResponseEntity<Data> getData(#RequestHeader(value="Accept-Language") String acceptLanguage)
{
//your code goes here
}
Once you get the accepted language info from your client' then you can read language deppendent values from a property file with Java I18N. The following article explain you the way how to do it: https://www.google.hu/amp/s/www.journaldev.com/1370/java-i18n-internationalization-in-java/amp
Finnaly if the language info is not provided by client you can use english language as a default.
Hope that it will help you.

The standard way of detecting user locale in web applications which can be reused in REST services is accept-language header. Browsers send this header with every request automatically. When it comes to detecting user locale in Spring MVC applications Spring provides us with a variety of *LocaleResolver classes that do the job for us. Please refer this article for simple example.
Provided that you are using Spring REST extension to Spring MVC then it is no different here. Everything that is available for MVC can be used in #RestController ones. So you clients may set the accept-language on their requests and automatic detection will work the same way as in web application.
If you have a requirement implement a solution with locale as a POST/GET parameter then you should have a look at LocaleContextHolder. Spring associates a locale information with the current Thread and this is a way to directly access and modify it. When you set the locale using LocaleContextHolder later you can use it in your app components reading form the context as well as Spring standard components will be aware of another locale set.

Related

configuration based API request response mapping in java

I have requirement where i want to integrate different Service providers REST APIs and switch to one of them based on request parameter.
Example if request parameter has type ="A" than I will be redirecting request to Service Provider A , get data ,map it and then respond back to client.
If type = "B" I will be redirecting request to Service Provider B and same applies for C...Z Types
Here One solution i can think of is having factory Pattern and get Client based on the type. and for Request/Response mapping i have to maintain Mapper classes for each Service Provider.
Is there any framework in java where i can make this configuration based, like all Request/Response mapping will be maintained in either xml/json file and the framework will take care of everything else.
And this can be plug and play kind where in future if new Service Provider is integrated than no code changes are required and the new Service Provider can be integrated by adding Request/Response mapping file directly.

How to use caching to improve performance of OAuth2 ResourceServer in Spring Boot

I am trying to use externalized Authorization Server and Resource Server protected with OAuth2. Spring Boot allows multiple ways of securing Resource Server with externalized Authorization Server by using RemoteTokenServices or providing user-info-uri. I am using user-info-uri for validating tokens on the resource server.
With this arrangement whenever a request reaches a ResourceServer it simply makes a REST call to user-info-uri using OAuth2RestTemplate. This will overwhelm Authorization Server when there is increased traffic. That is why I want to cache the results for the first call and in the subsequent calls I will check the presence of Token in the cache. If it is present I want to simply allow the request to reach the controller else I want to call user-info-uri.
How to achieve this. I am using JWT for tokens. I know when I use JWT I could provide public key to the resource server but I am not sure if it is the good way since I have too many Resource Servers.
I tried providing UserInfoRestTemplateCustomizer Bean as suggested in here https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/#oauth2-boot-resource-server-custom-user-info but not sure what to do here.
I think you will want to supply a custom implementation of the User Service which is used by the Spring Security Context, when it converts a JWT to the AuthenticationContext. The default behavior will call out to the User Info Endpoint, should you have one configured.
It is possible to provide a custom OidcUserService when configuring the security context. From https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#oauth2login-advanced-oidc-user-service
Another alternative is apply a custom JwtAuthenticationConverter (see HttpSecurity.oauth2ResourceServer().jwtAuthenticationConverter ), which can deal with issues when converting a jwt to authentication. Check out https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#oauth2resourceserver-authorization
Hope this helps
I found that the default handling did not give me the control I wanted. These were my requirements:
https://authguidance.com/2017/10/03/api-tokens-claims/
Here is the code I ended up using, since I could not get the claims I wanted into the access token.
My example is a little complex but I hope it helps you understand some options for extending Spring Boot default processing ..

Exposing a web site through web services

I know what I am asking is somehow weird. There is a web application (which we don't have access to its source code), and we want to expose a few of its features as web services.
I was thinking to use something like Selenium WebDriver, so I simulate web clicks on the application according to the web service request.
I want to know whether this is a better solution or pattern to do this.
I shall mention that the application is written using Java, Spring MVC (it is not SPA) and Spring Security. And there is a CAS server providing SSO.
There are multiple ways to implement it. In my opinion Selenium/PhantomJS is not the best option as if the web is properly designed, you can interact with it only using the provided HTML or even some API rather than needing all the CSS, and execute the javascript async requests. As your page is not SPA it's quite likely that an "API" already exists in form of GET/POST requests and you might be lucky enough that there's no CSRF protection.
First of all, you need to solve the authentication against the CAS. There are multiple types of authentication in oAuth, but you should get an API token that enables you access to the application. This token should be added in form of HTTP Header or Cookie in every single request. Ideally this token shouldn't expire, otherwise you'll need to implement a re-authentication logic in your app.
Once the authentication part is resolved, you'll need quite a lot of patience, open the target website with the web inspector of your preferred web browser and go to the Network panel and execute the actions that you want to run programmatically. There you'll find your request with all the headers and content and the response.
That's what you need to code. There are plenty of libraries to achieve that in Java. You can have a look at Jsop if you need to parse HTML, but to run plain GET/POST requests, go for RestTemplate (in Spring) or JAX-RS/Jersey 2 Client.
You might consider implementing a cache layer to increase performance if the result of the query is maintained over the time, or you can assume that in, let's say 5 minutes, the response will be the same to the same query.
You can create your app in your favourite language/framework. I'd recommend to start with SpringBoot + MVC + DevTools. That'd contain all you need + Jsoup if you need to parse some HTML. Later on you can add the cache provider if needed.
We do something similar to access web banking on behalf of a user, scrape his account data and obtain a credit score. In most cases, we have managed to reverse-engineer mobile apps and sniff traffic to use undocumented APIs. In others, we have to fall back to web scraping.
You can have two other types of applications to scrape:
Data is essentially the same for any user, like product listings in Amazon
Data is specific to each user, like in a banking app.
In the firs case, you could have your scraper running and populating a local database and use your local data to provide the web service. In the later case, you cannot do that and you need to scrape the site on user's request.
I understand from your explanation that you are in this later case.
When web scraping you can find really difficult web apps:
Some may require you to send data from previous requests to the next
Others render most data on the client with JavaScript
If any of these two is your case, Selenium will make your implementation easier though not performant.
Implementing the first without selenium will require you to do lots of trial an error to get the thing working because you will be simulating the requests and you will need to know what data is expected from the client. Whereas if you use selenium you will be executing the same interactions that you do with the browser and hence sending the expected data.
Implementing the second case requires your scraper to support JavaScript. AFAIK best support is provided by selenium. HtmlUnit claims to provide fair support, and I think JSoup provides no support to JavaScript.
Finally, if your solution takes too much time you can mitigate the problem providing your web service with a notification mechanism, similar to Webhooks or Resthooks:
A client of your web service would make a request for data providing a URI they would like to get notified when the results are ready.
Your service would respond immediatly with an id of the request and start scraping the necessary info in the background.
If you use skinny payload model, when the scraping is done, you store the response in your data store with an id identifying the original request. This response will be exposed as a resource.
You would execute an HTTPPOST on the URI provided by the client. In the body of the request you would add the URI of the response resource.
The client can now GET the response resource and because the request and response have the same id, the client can correlate both.
Selenium isn't a best way to consume webservices. Selenium is preferably an automation tool largely used for testing the applications.
Assuming the services are already developed, the first thing we need to do is authenticate user request.
This can be done by adding a HttpHeader with key as "Authorization" and value as "Basic "+ Base64Encode(username+":"+password)
If the user is valid (Users login credentials match with credentials in server) then generate a unique token, store the token in server by mapping with the user Id and
set the same token in the response header or create a cookie containing token.
By doing this we can avoid validating credentials for the following requests form the same user by just looking for the token in the response header or cookie.
If the services are designed to chcek login every time the "Authorization" header needs to be set in request every time when the request is made.
I think it is a lot of overhead using a webdriver but it depends on what you really want to achieve. With the info you provided I would rather go with a restTemplate implementation sending the appropriate http messages to the existing webapp, wrap it with a nice #service layer and build your web service (rest or soap) on top of it.
The authentication is a matter of configuration, you can pack this in a microservice with #EnableOAuth2Sso and your restTemplate bean, thanks to spring boot, will handle the underlining auth part for you.
May be overkill..... But RPA? http://windowsitpro.com/scripting/review-automation-anywhere-enterprise

User's locale in microservice - JHipster

In one of the microservices, in a JHipster microservice architecture, I want to generate a document, in the users' language.
In the gateway, the users' language is retrieved by a cookie (AngularCookieLocaleResolver). But when a request, routed through the gateway, arrives at the microservice, no cookies are found on the request.
I see a few options here:
Add a locale claim to the JWT-token
Contact the gateway with the username, to retrieve the locale
Do not generate locale specific content at a microservice
I would prefer the first option, but maybe there are some better options...
Can anyone help me choose or list up alternatives?
First option using JWT claim makes sense and it could be proposed as an enhancement request to JHipster project. I can see one minor drawback: any user changing her locale won't get correct localised content until token expires or she logs out and re-authenticates.
An alternative would be to pass the locale as a parameter of your resources requests, this makes sense as client is supposed to know it and also in a broader scope client could a be a partner application using another kind of authentication like an API key.

Set Request Header and Forward to another application

I am writing a Java based Web application, which, in the actual production environment would be front-ended by another application which would set certain HTTP request headers before the request hits my application.
However, in the development environment I do not have the front-ending application, for which I need to create a mock web application that simulates the same behavior. i.e. this mock application should set the request headers and redirect or forward or whatever that I do not know :) to a certain page in my application.
How can I accomplish this?
The following articles may help you:
Adding Header Information to an existing HTTP Request
How to modify request headers in a J2EE web
application.
P.S.
I am sorry I provided only links, that was one of my early answer on SO ))
In case you don't want to modify your code as suggested by #user1979427 you can use a proxy server to modify headers or add headers on the fly.
For example in Apache HTTPD you would add something like below and proxy the
Header add HEADER "HEADERVALUE"
RequestHeader set HEADER "HEADERVALUE"
Refer to HTTPD doc
You should create a AddReqHeaderForFrowardWrapper request wrapper passing the headername and header values. And, override the request header related methods to return your custom header.
You can use Tracer to implement this.
There are frameworks available to support this implementation.
Spring has Sleuth, Zipkin, OpenTracing available.
I find OpenTracing to be easy to use without worrying about dependency conflicts.
Read more about it here: https://opentracing.io/guides/java/
Instead of writing a mock application, I used a browser add-on that allowed me to add custom headers!
For setting header in java, you can use:
request.setHeader(attributeName, attributeValue);
And for redirecting to another page, you can use:
request.sendRedirect(URL);

Categories

Resources