I have a Spring Boot application exposing some endpoints for REST requests. I am trying to decouple two components (which currently call each other's code directly), and I want them to make REST requests to each other (for an eventual microservice implementation). I know endpoint discovery can be done through a discovery service (e.g. Eureka), but is there a way to also communicate parameter information from the service which requires it to the client requesting it?
Example: I have a shopping cart service which relies on information about products available for purchase. Using Eureka (or another service discovery tool) I can register my services so that the shopping cart service is now aware of the product service. If the product service has something like:
#GetMapping("/product")
public Product findById(#RequestParam int id) {
return products.find(id);
}
I know to use this endpoint to get product with ID 3 the cart service would have to make a request to http://localhost:1234/product?id=3, but is there a way that it can discover these parameters and their required types at run time? In my example, if I use Eureka, the shopping cart service is dynamically made aware of the product service's location, but is not made aware of the parameters that its endpoints will accept. I know Spring Boot Actuator is supposed to provide this information, but whenever I use it, the params field for my endpoints is always empty.
Is there a way that it can discover these parameters and their required types at run time?
Do you really need this information at runtime?
Because it would be much simpler if you need this at development time. Then you could just use something like Swagger, which will provide a service specification endpoint. It can even generate a client for your service.
But, if you really want it at runtime, you may be better served with a HATEOAS API. HATEOAS (Hypermedia as the Engine of Application State) means that your API is navigable. That means that clients can "crawl" you API following the links presented, like a human navigating through a website. How useful it will be, depend on what you are trying to achieve.
There are two popular "solutions" to this:
HAL (Hypertext Application Language) - Still an Internet Draft
JSON-LD (JSON for Linking Data) - A W3C Standard
Spring Boot has HAL support, see spring-boot-starter-hateoas.
You can use parameter map, that will be dynamically populated with all used parameters:
#GetMapping("/product")
public Product findById(#RequestParam Map<String,String> allRequestParams) {
return products.find(allRequestParams.get("id"));
}
You can iterate the parameter map to find which parameters are present.
You can use Swagger in your product service to generate apis, exposed in a json file. For example you can look at sample project petstore with its json exposed, containing apis and parameters with definition.
Then in your shopping cart service you can navigate at runtime product service apis, iterating for specific api parameters.
Related
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.
I am planning on hosting my REST API in a VM in a VNET where the only point of entry is via Azure API Management.
I have multiple back ends so the API Management will route to a different backend base url depending on the group the user is in and the backend will also return different data depending on the user making the call.
Since the Azure API Management can handle authorisation, JWT validation and setting headers etc what type of authorisation code should I put in my REST API application?
Should I try to validate the JWT again in my Java code or just parse the headers?
i.e. is it safe to code it as a public API and trust that the headers have been set correctly by API Management?
Or should I make a call to Azure Active Directory from the Spring controller every time to validate that the user does actually exist in the specified group and that the group specified is the one expected for this backend?
If so, how would I do that from Java and how would I inject an offline version when running locally?
Since your API will be inside a VNET it'll be protected as it is. But, there is really no reason to just have it open. The more layers of protection you can add the better your chances to whistand a potential attack.
So see whatever is most convenient to you. You can rely on APIM doing user authentication and authorization and avoid doing that in your backend API. But it would be a good idea to check if call made to your backend API is coming from APIM, and you can do that by sending credentials from APIM. The best option here would be client certificates: https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-mutual-certificates
But you can also send basic credentials: https://learn.microsoft.com/en-us/azure/api-management/api-management-authentication-policies#Basic
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
I am using the Jersey implementation of JAX-RS spec to develop RESTful web services. There is a url that can uniquely identify a resource. Is there a way to let know the user of the RESTful services, the possible actions that can be performed on the resource? For example,
Resource name - host1
http://localhost:8080/state-fetcher/rest/object/host1/actions
This should give me all the possible actions that can be performed on the resource - {actions: [GET, POST, DELETE]}
Thanks!
Use the OPTIONS HTTP method on the resource. You will get the allowed methods in Allow header, for example: Allow: GET, HEAD, PUT and in a payload you will find the fragment of wadl associeted with the specified resource.
A RESTful service itself is inteded to be self- descriptive! If the user performs a request, the REST service should send back a list of possible links, which can be performed next, along with the response. That's the motivation and general concept of a RESTful serivice. If you provide a graphical WebClient, you just need to provide the initial link (e.g. http:\example.com\restful), and the response sends back a list of valid links which just needs to be visualized within the GUI. Usually the webservice only provides those links which are accessible in terms of the users role. (This is not a security feature!!! It just prevents that unecessary links are displayed) Otherwise the OPTION method of the HTTP protocol provides information concerning the supported protocol methods.
Am developing an app using SpringMVC. In that app, I have a list of crud screens(almost 20 screens).
Now, I designed my controller in the following pattern of request mapping
create
show
update
delete
Here , the problem is, I would like to expose this URL as both REST Service as Well as Normal Spring controller(directs to a new page after CRUD operations).
ie. When I use the application, it should do the CRUD operation and redirect to specific pages(Accordingly)
When I call as a rest service (using REST Clients). I should get the JSON data
Is it possible??
I would cleanly separate your AJAX/JSON calls from your page navigation. In other words, assign responsibility for the page navigation to one controller (or leverage an SPA routing mechanism on the client side), and the data access to another "service" controller. You then have a reusable and testable service and an independent navigation flow (which could evolve, change technologies etc).
As far as know, I don't think so. But one way will be like, each time your controller will produce JSON response. But for web application you need to add extra call for each request which will load desired page and then call your CRUD methods on load of your page and parse the JSON response to fill the data.
I think what you are looking for is content negotiation. Google recommends this article: http://blog.springsource.org/2013/05/11/content-negotiation-using-spring-mvc/