I have a condition where I want to use the same method to be called for request coming from mobile app and request coming from webapp with different clientId and different Client secret and redirect uris,base uris .
When a request comes from mob we have header "source" value as mobile and when request comes from web we have header "source" value as web.
I want to have something like that when request comes from web ,values of client id,clientsecret,baseurl,redirecturl of web is loaded and when request comes from mobile
values of client id,clientsecret,baseurl,redirecturl of mobile is loaded.
I want to avoid to write the same logic either by creating in different method or different endpoint for mobile/web.I wan to use the same method and the same endpoint ,just that values injected from conifguration will be different based on the header value
How can I achieve this??Is there a way to #Autowire different config class based on condition
TokenController
public class TokenController {
#GetMapping("/getToken")
public ResponseEntity<?> fetchToken(#RequestParam("foo") String foo) {
ResponseEntity<?> tokenInfo = tokenInfoServiceImpl.getTokenDetails(foo);
return tokenInfo;
}}
TokenServiceImpl
public class TokenServiceImpl{
#Autowired
SSOConfig ssoConfig;
public ResponseEntity<?> getTokenDetails(String foo) {
HttpHeaders tokenExchangeHeaders = prepareRestTemplateHeader(ssoConfig.getClientId(),
ssoConfig.getClientSecret());
String baseUrl =soConfig.getBaseurl();
String redirectUrl = ssoConfig.getRedirectUrl();
//rest of the logic
}
}
SSOConfig class
#Configuration
#ConfigurationProperties(prefix = "sso.web")
public class SSOConfig {
private String baseurl;
private String redirectUrl;
private String tokenClientId;
private String tokenClientSecret;
//Getters and Setters
}
For your TokenController class, you should be able to add an argument to process a RequestHeader.
public class TokenController {
#GetMapping("/getToken")
public ResponseEntity<?> fetchToken(#RequestHeader(name = "source") String source, #RequestParam("foo") String foo) {
ResponseEntity<?> tokenInfo = null;
if ("mobile".equals(source)) {
ResponseEntity<?> tokenInfo = tokenInfoServiceImpl.getTokenDetails(foo);
} else {
//do something else
}
return tokenInfo;
}}
There's a great tutorial on this at Baeldung
Related
I used Lombok, Open Feign and Spring Web
I have currencyClient interface:
#FeignClient(value = "getcurrency", url = "https://openexchangerates.org")
public interface currencyClient {
#RequestMapping(value = "/api/historical/2012-07-10.json/{smt}", method = RequestMethod.GET)
public List<Object> getCurrency(#PathVariable String smt);
}
And Controller:
#RestController
#RequiredArgsConstructor
public class StatusController {
private String appId1 = "appId";
private final currencyClient currencyClient;
#GetMapping("/getAllCurrency")
public List<Object> getCurrency(){
return currencyClient.getCurrency(appId1);
}
}
And "http://localhost:1212/getAllCurrency" is not working cause the link is converted into "**https://openexchangerates.org/api/historical/2012-07-10.json/appId**" I understand that &/= are reversed and I also think that my indication of List is not correct. That's what I tried so how can I get info from "**https://openexchangerates.org/api/historical/2012-07-10.json?app_id**" as "http://localhost:1212/getAllCurrency"?
According to the https://docs.openexchangerates.org docs, the app_id should be a request parameter (see #RequestParam), not a path variable. You could do something like this:
CurrencyClient interface:
#FeignClient(value = "getcurrency", url = "https://openexchangerates.org")
public interface CurrencyClient {
#RequestMapping(value = "/api/historical/2012-07-10.json", method = RequestMethod.GET)
Map<String, Object> getCurrency(#RequestParam("app_id") String appId);
}
StatusController:
#RestController
public class StatusController {
private final CurrencyClient currencyClient;
public MyController(CurrencyClient currencyClient) {
this.currencyClient = currencyClient;
}
#GetMapping("/getAllCurrency")
public Map<String, Object> getCurrency() {
String appId1 = "*****";
return currencyClient.getCurrency(appId1);
}
}
Some additional things to note here:
Please don't post yout API key to StackOverflow, or anywhere else publicly. Other people might abuse it. Since you already posted it, you should request a new API key and get rid of this one (close it if possible).
I am trying to write a feign client to make calls to retrieve data from a server where the api accepts a list of identical named query parameters to determine how much data is being asked. Here is an example url I am trying to hit:
http://some-server/some-endpoint/{id}?include=profile&include=account&include=address&include=email
So far for my feign client I'm attempting to set it up this way:
#FeignClient("some-server")
public interface SomeServerClient {
#RequestMapping(method = RequestMethod.GET,
value = "/customers/api/customers/{id}",
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
Map<Object, Object> queryById(
#PathVariable long id,
#RequestParam("include[]") String ... include);
default Map<Object, Object> queryById(long id) {
return queryById(id,"profile", "account", "address", "email");
}
However this doesn't appear t format the request in the way desired, so my question is how can I set up my feign client to submit its request to the url as shown in the example above?
use #RequestParam("include") List<String> includes, example:
client:
#FeignClient(value = "foo-client")
public interface FooClient {
#GetMapping("/foo")
Foo getFoo(#RequestParam("include") List<String> includes);
}
controller:
#RestController
public class FooController {
#GetMapping("/foo")
public Foo getFoo(#RequestParam("include") List<String> includes) {
return new Foo(includes);
}
}
usage:
List<String> includes = new ArrayList<>();
includes.add("foo");
includes.add("bar");
Foo foo = fooClient.getFoo(includes);
url:
http://some-server/foo?include=foo&include=bar
in the below example, i am using POST and GET methods. post is to initialize a varibale and GET is to get this varibale.
I use Postman to make the requests.
i am receiving an error
#RequestBody(value = "val") //cant resolve method value
please let me know how to fix the belwo error so i can use post method for initialization and get methdo to retrieve the value
Controller1
#Controller
#RequestMapping("/call1")
public class Call1 {
public String str = "inti";
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody(value = "val") String val) {
this.str = val;
}
#RequestMapping(value = "/getparam1", method = RequestMethod.GET)
public String getParam1() {
return this.str;
}
}
Create a class Variable and use other code in controller.
class Variable {
String data= 'val';
}
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody Variable val) {
this.str = val.data;
}
When making a request pass json as {"data":"12345"}
and then use #RequestBody Variable v in code instead of String as it will serve your purpose of default value and will make the code extensible as you can add different properties to the existing variable in future if needed.
When to use #RequestBody?
You can not use value with it. You can use this when you have multiple field entity which you want to perform the operation. Let's say you want to save the user then you may need to create User Model first and use in a controller #RequestBody.
Model:
public class User
{
#Id
private int id;
private String firstname;
private String lastname;
//Getters-Setters, AllArgConstructor-constructor
}
#RequestMapping(value = "/requestBodyExample", method = RequestMethod.POST)
public String intiParam1(#RequestBody User user) {
return user.getFirstname();
}
Quick Start with Spring Boot
I have a problem with my REST Controller. If I sent a request with a RequestBody (json) some attributes doesn't arrive the controller, although they was sent and defined at model.
I could find out that it look like an old version of files will be used from the local java web server. As I changed the System.out.println Value at Constructor still the old value was outputed.
public RestController_ApiKey_2_0() {
System.out.println("RestController_ApiKey_2_0 init");
}
I tried the following things bootless:
deleted java web server and did a new installation
cleaned the project and started server again
clean install of project
Does anyone have an idea?
Please provide more code, how do you declare a controller, and what params it can take. Also show a sample request.
Here is an example of a simple controller:
A model
public class CustomRequestBody {
private String fieldA;
private String fieldB;
public String getFieldA() {
return fieldA;
}
public void setFieldA(final String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(final String fieldB) {
this.fieldB = fieldB;
}
}
Controller:
#Controller
public class MyController {
#RequestMapping(value = "/some-path", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ACCEPTED)
public ResponseEntity handleSomePath(#RequestBody final CustomRequestBody body, final HttpServletRequest request) {
// Do the job.
}
And request will be:
HTTP POST http://some.server.com/some-path
{
"fieldA":"first value",
"fieldB":"second value"
}
Read more at Spring documentation here
When creating or listing and item using REST api I return also the whole resource path.
For example creating a person record returns http://service:9000/person/1234in response. In order to get schema, host & port part like http://service:9000, I extract it from URL obtained by HttpServletRequest.getRequestURL().
Example (not the production code but conceptually same):
#RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(
#RequestParam(value = "name") String name,
HttpServletRequest req) {
long id = createPerson(name);
String uriStart = RestUtils.getSchemeHostPortUrlPart(req
.getRequestURL().toString());
String uri = uriStart + "/person/" + id;
Person person = new Person(name, id, uri);
return person; //Serialized to json by Spring & Jackson
}
//Simple bean-like class
public class Person {
//Getter methods for uri, name & id
}
Since this is quite a boiler plate code which repeats in every method I was wondering if Spring does not have support for this which eluded me when reading it's documentation.
By this I mean accessing either URL without neededn HttpServletRequest or even better its schema, host, port part only.
The documentation provides a lot of examples for constructing URIs using a UriComponentsBuilder.
Furthermore I recommend to take a look at Spring HATEOAS if you want to take your REST API to the next level.
BTW: PUT means that you place what you send (request body) to the location to which you send it (URL). If nothing is there something new is created, otherwise what exists is updated (replaced).
This is not what is happening in your example. The proper way would be to either POST to /person or PUT to the person's own URL, e.g. /person/1234, provided you have the ID beforehand.
You can construct the URI in an interceptor (that's executed previous to controller methods) and put it as an attribute and use it in the controller method.
I believe it is quite simple. Look at this example:
#RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(#RequestParam(value = "name") String name, HttpServletRequest req) {
long id = createPerson(name);
Person person = new Person(id, name, req);
return person; //Serialized to json by Spring & Jackson
}
public class JsonResponse {
private String url;
public JsonResponse(HttpServletRequest request) {
url = request.getRequestURI() + "?" + request.getQueryString();
}
public final String url() {
return url;
}
}
public class User extends JsonResponse {
private Long id;
private String name;
public User(Long id, String name, HttpServletRequest request) {
super(request);
this.id = id;
this.name = name;
}
// Getter, Setter
}
You can use org.springframework.web.servlet.support.ServletUriComponentsBuilder like this:
String uri = ServletUriComponentsBuilder.fromCurrentRequest()
.replacePath("/person/{id}")
.buildAndExpand(id)
.toUriString();