I have a controller:
#PostMapping("/name/**")
public Mono<String> doSomething(HttpEntity<byte[]> requestEntity,
ServerHttpRequest serverHttpRequest) {
String restOfTheUrl = //the ** part is what i need here
return webClient.forwardRequest(requestEntity, serviceUrl + "/" + restOfTheUrl);
}
How do I obtain the URL string (including all query params) thats after the /name/ ?? basically I need the ** part. Of course I can remove the /name/ from serverHttpRequest.getPath(..) but is there a better way?
#PostMapping("/name/{*path}")
public Mono<String> doSomething(#PathVariable("path") String path) {...
Related
today I met with an interesting problem. I want to conduct a user registration process with a unique link.
My registration link is built with serverName, serverPort and contextPath parameters. I need these three parameters with randomly generated UUID to create a unique URL, which will be responsible for user registration. Currently I am passing HttpServletRequest as a param in the controller method and after all, I started to wonder if this is a good practice to conduct URL generating on the controller side.
UserSevice:
public void register(User user, String appUrl) {
user.setStatus(UserStatus.INACTIVE);
user.setRoles(Collections.singleton(new Role(RoleType.ROLE_USER)));
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(user);
verificationTokenService.sendConfirmationEmail(user, appUrl);
}
UserController:
#PostMapping("/registration")
public ResponseEntity registerUserAccount(
#RequestBody #Valid User user, HttpServletRequest request) {
String appUrl = "http://" + request.getServerName() + ":" +
request.getServerPort() + request.getContextPath();
userService.register(user, appUrl);
return ResponseEntity.ok().build();
}
I know that I can create a helper method like:
public String getServerName(HttpServletRequest request) {
return request.getServerName();
}
public int getServerPort(HttpServletRequest request) {
return request.getServerPort();
}
public String getContextPath(HttpServletRequest request) {
return request.getContextPath();
}
to get this parameter but still, I need to pass HttpServletRequest as a parameter and this is a problem due to the fact that this is an interface.
String appUrl =
"http://"
+ getServerName('this method require HttpServletRequest').getServerName()
+ ":"
+ getServerPort('this method require HttpServletRequest').getServerPort()
+ getContextPath('this method require HttpServletRequest').getContextPath();
Current solution works but I am interested in if there is another option to get these three parameters without passing HttpServletRequest as an argument on the controller side and avoid generating URL there. Thanks for any help.
I have url like http://www.example.com/api/{uriparam}/something
How should I replace the uriparam with my parameter call test?
So that it will be like http://www.example.com/api/test/something
In rest API its called as path, to do that, here is sample of controller using path. here is sample with jax rs.
#Path("/testUrl/{data}")
#GET
public String checkPending(#PathParam("data") String data) {
String yourUrl = "http://www.example.com/api/" + data + "/something";
return yourUrl;
}
You can use org.springframework.web.util.UriComponentsBuilder as below :-
Map<String, String> parameters = new java.util.HashMap<String,String>();
parameters.put("uriparam","test");
String url = UriComponentsBuilder.fromHttpUrl("http://www.example.com/api/{uriparam}/something".trim()).buildAndExpand(parameters).encode().toString();
it will return you the required url
I use this Java client to make POST requests:
Implementation
public Mono<PaymentResponse> executeAndReceive(String transaction) {
Mono<String> transactionMono = Mono.just(transaction);
return client.post().uri(gatewayUrl + "{token}", token)
.retrieve()
.bodyToMono(Response.class);
}
I use this code to call the client:
String GATEWAY_PROCESSING_URL = http://www.some_host:8080/rest_api/v1/
String token = 342552334
RestClient client = RestClientBuilder.builder()
.gatewayUrl(GATEWAY_PROCESSING_URL)
.token(token)
.usernamePassword(user_name, password)
.build();
But sometimes I forgot to set / at the end of the URL.
Is there some way to detect this and set it automatically if it's missing?
If all you need is a safety check whether the url ends with a '/' just use the example below.
String url = ... some url ...
if (url.endsWith("/") == false) {
url += "/";
}
When I Type Base Url="https://www.bkashcluster.com:9081/dreamwave/merchant/trxcheck/sendmsg/" with last slash(/) then give me message like this:
Response{protocol=http/1.1, code=500, message=Internal Server Error, url=https://www.bkashcluster.com:9081/dreamwave/merchant/trxcheck/sendmsg/?user=XX&pass=r#12&msisdn=0160000000&trxid=6BM3KRWHLB}
After "sendmsg" slash(/) does not need
And When I Type Base Url="https://www.bkashcluster.com:9081/dreamwave/merchant/trxcheck/sendmsg" with out last slash(/) then apps unfortunately stop;
For this I Want to remove last "/" any way from Base Url.
private void requestDataForBkashTransaction() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.bkashcluster.com:9081/dreamwave/merchant/trxcheck/sendmsg/")
.addConverterFactory(GsonConverterFactory.create())
.build();
InstituteService api = retrofit.create(InstituteService.class);
String urlString=String.format("?user=Exampll&pass=12345&msisdn=0160000000&trxid=6BM3KRWHLB");
Call<List<Transaction>> call=api.getBkashTrasactionCode(urlString);
call.enqueue(new retrofit2.Callback<List<Transaction>>() {
#Override
public void onResponse(Call<List<Transaction>> call, retrofit2.Response<List<Transaction>> response) {
if(!response.isSuccessful()){
Toast.makeText(PaymentActivity.this, response.code(), Toast.LENGTH_LONG).show();
return;
}
List<Transaction> transactions=response.body();
for(Transaction transaction:transactions){
String content="";
content+=transaction.getTrxId();
textView.append(content);
}
}
#Override
public void onFailure(Call<List<Transaction>> call, Throwable t) {
}
});
}
#GET
Call<List<Transaction>> getBkashTrasactionCode(#Url String url);
This is not how you add query parameters to a call using retrofit. Response code 500 Internal Server Error indicates that. Please refer to this this and add queries properly, then it should work.
To remove last slash,
you have to remove last path from the baseUrl with ../ first, then append it at your urlStirng instead.
String urlString=String.format("../sendmsg?user=Exampll&pass=12345&msisdn=0160000000&trxid=6BM3KRWHLB");
First assign your baseUrl to a String variable and remove the last character as below.
String baseUrl = "https://www.bkashcluster.com:9081/dreamwave/merchant/trxcheck/sendmsg/";
if (baseUrl.endsWith("/")) {
String newBaseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
In this example, the URL for a service has the form /projection/projectionId:
#Stateless
#Path("projection")
public class ProjectionManager {
#Inject
private ProjectionDAO projectionDAO;
#Inject
private UserContext userContext;
#GET
#Path("{projectionId}")
#Produces("application/json")
public String places(#PathParam("projectionId") String projectionId) {
return projectionDAO.findById(Long.parseLong(projectionId)).getPlaces().toString();
}}
How can I pass two (or more) query parameters to access the service using this code:
#PUT
#Path("/buy")
public Response buyTicket(#QueryParam("projectionId") String projectionId, #QueryParam("place") String place) {
Projection projection = projectionDAO.findById(Long.parseLong(projectionId));
if(projection != null) {
projectionDAO.buyTicket(projection, userContext.getCurrentUser(), Integer.parseInt(place));
}
return Response.noContent().build();
}
/buy?projectionId=value1&place=value2
Take a look at https://en.wikipedia.org/wiki/Query_string for further information. And since it is HTTP PUT you cannot simply open that URL in your browser, you can write some simple REST client or use browser extension like Postman in Chrome.
Query parameter is the thing after the ? in the URI, while path parameter is the parametrer before the ? in the URI.
If you need two inputs to your method, you can go with any combination of query param and path param => four combinations
It's a good convention that path params should denote some kind of identity of the resource, because it's part of it's address, while query params more some form/shape/filtering of the response.
In your case, I'd encode both params as path parameters, so the code would look like this:
#PUT
#Path("/buy/{projectionId}/place/{place}")
public Response buyTicket(#PathParam("projectionId") String projectionId, #PathParam("place") String place){
Projection projection = projectionDAO.findById(Long.parseLong(projectionId));
if(projection != null){
projectionDAO.buyTicket(projection, userContext.getCurrentUser(), Integer.parseInt(place));
}
return Response.noContent().build();
}
The URL would look like:
${host}/buy/1337/place/42
Thanks for your input guys, I have fixed it.
It looks like I had to add the path parameter to the additional parameters, and pass additional parameters on the request, instead of the path parameter. Code looks as below,
it('should get a customer, searches with a customer name', (done) => {
var pathParams = {};
var body = {};
var additionalParams = {
queryParams: {
name: 'Ominathi'
}
};
//apigClient.invokeApi(pathParams, '/customer', 'GET', queryParams, body)
apigClient.invokeApi(pathParams, '/customer', 'GET', additionalParams, body)
.then(response => {
expect(response.status).toBe(200);
done();
})
.catch(err => {
fail(err);
done();
});
});
Thanks.
Ref: https://www.npmjs.com/package/aws-api-gateway-client