I have a server web app implemented with rest services and I want to make a client web application. I have to make the communication using UrlConnection and I don't really know how to make it.
My server app looks like this:
#Controller
public class PersonController {
private PersonDs personDs;
public void setPersonDs(PersonDs ds) {
this.personDs = ds;
}
#Secured(value = { "ROLE_ADMIN" }
#RequestMapping(method = RequestMethod.GET, value = "/person/{id}")
public ModelAndView getEmployee(#PathVariable String id) {
Person e = personDs.get(id);
return new ModelAndView("person", "object", e);
}
}
Until now I have seen the result in a jsp page "person" but now I need to introduce the client app. My controller should return the data in a json format which will be sent to the client, and the client will render the information in a Html page. But how can I make the connection between #RequestMapping(method = RequestMethod.GET, value = "/person/{id}") and the client request..? What the client request url should look like?
Related
I have been working with .NET Core for only a few weeks. Now I have a question about a Web API that I created for a project.
I need to call an external API, however all the documentation I see is for applications with MVC. This means they have a main page, which I
don't have and don't want, because I just want to call this API on an new endpoint and to be consume on client side.
If I test the external API in postman it returns something like this:
postman response
I tried to follow along with the official documentation of Microsoft Call a Web API From a .NET Client (C#) however I get to a point where I'm not sure how to proceed.
I've create a model with a few of the result properties that I want to capture from the call to this endpoint shown in the first image and a simple controller that I want to be the final endpoint that return the information from this external API.
These are the things that I have already:
Model class Product:
namespace MyProyect
{
public class Product
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
}
}
Controller to consume the external API:
namespace MyProyect.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ThirdPartyAPIController : ControllerBase
{
static HttpClient client = new HttpClient();
[HttpGet]
static async Task<Product> GetProductsAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product!;
}
}
}
I don't really know how to proceed from here, this is all I can get from the documentation. I want this controller to be an endpoint that the user can consume. But this is not even appearing on the Swagger UI screen.
Is there an easy way to do this? Am I using an incorrect way?
First register a HttpClient for your Controller/Service
// In Startup.cs (5.0)
services.AddHttpClient<ThirdPartyAPIController>();
// ... or in Program.cs (6.0)
builder.Services.AddHttpClient();
Then inject the HttpClient and use it in the Controller method.
namespace MyProyect.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ThirdPartyAPIController : ControllerBase
{
// Let the `IHttpClientFactory` do the `HttpClient` handling
private HttpClient _client;
public ThirdPartyAPIController(HttpClient client)
{
_client = client;
}
[HttpGet]
// use `public` instead of `static`
// only this is then visible in Swagger UI
public async Task<Product> GetProductsAsync(string path)
{
Product product = null;
HttpResponseMessage response = await _client .GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product!;
}
}
}
Like written in the code comment. You have to use public (not static) for the controller method to be registered and visible in Swagger UI.
Please suggest spring restful web service ..I have one doubt if iam having web service in one dynamic web project how can i get the value in client side(or)
For Example:
client side(Dynamic web project) iam giving two data 2 and 3 how to send this data to server side(onather Dynamic web project) for addition purpose is that possible.how server get data from client which is in another project.suggest some codes.
You can have any number of projects in single eclipse workspace working individually say WSClient (WS Client code) and WSServer (WS developed and deployed using this) two separate projects.
Here is the sample SpringController using Spring MVC to develop RESTful service:
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class SpringRestController {
#RequestMapping(method = { RequestMethod.GET }, value = { "/testApplication" }, consumes = MediaType.ALL_VALUE, produces = MediaType.ALL_VALUE)
public String getServerInfo() {
System.out.println("I got hit");
String message = "Hit the end point";
return message;
}
}
Once you deployed the above service then you can consume this using even Browser. Once done that then use Service Client to consume the same.
There are many frameworks you can use to consume the REST web-service, one of them i had used is Jersey which is implemented based on the JAX-RS specification.
Below is the sample Code of Jersey client consuming REST Web-service
REST WS Project
//Person pojo
#JsonInclude(Include.NON_NULL)
public class Person implements Serializable {
private static final long serialVersionUID = 8979562848777300129L;
private String firstName;
private String lastName;
private String email
//setter and getter methods
}
//REST WS controller
#RestController
#RequestMapping("/user")
public class SBUserController{
#RequestMapping(value = "/profile", method = RequestMethod.GET, consumes = "application/json", produces = "application/json")
public Person fetchProfile() {
//implement service layer and dao layer to fetch user profile from DB
//testing purpose i am creating one person and returning back
Person person = new Person();
person.setFirstName("John");
person.setLastName("Terry");
person.setEmail("john#gmail.com");
return person;
}
}
//Client Side
Client client = Client.create();
WebResource webResource = client.resource("http://localhost:8080/user/profile");
ClientResponse clientResponse = webResource
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.get(ClientResponse.class);
if (clientResponse.getStatus() == 200) {
//You need to have the same Person bean class in client project also
Person person = clientResponse.getEntity(Person.class));
}
I'm using Angularjs and spring mvc 3. I have in my controller class:
#Controller
#RequestMapping(value = "/elprocesses")
public class ELProcessController {
...
#RequestMapping(value = "/elprocess", method = RequestMethod.POST)
public #ResponseBody void save(#RequestBody final Entity01 entity01,
#RequestBody final Entity02 entity02
) {
...
}
ELProcessController.js :
$scope.saveForm = function(selectedname01) {
$http.post('elprocesses/elprocess', {entity01:selectedname01, entity02:selectedname02});
...
}
it doesn't enter in my spring controller method, but when I send only one data with $http.post('elprocesses/elprocess', selectedname01);
and changing my controller class with:
#RequestMapping(value = "/elprocess", method = RequestMethod.POST)
public #ResponseBody void save(#RequestBody final Entity01 entity01)
this works fine,
What am I doing wrong to send entity01 and entity02?
In your javascript, is selectedname02 defined anywhere?
If it is, then open up your network tab and you'll see whether or not it's sending data. The POST request has the header Content-Type: application/json by default though so make sure you're trying to get json data and not form encoded data or something. I'm not familiar with spring mvc at all so check their docs.
I have worked on Web services using Jaxb earlier. I geneated Java from xsd, and then I used to post the xml request to the specified URL using HTTP post. Recently I heard about this Restful web services, on reading I felt that what I had been doing earlier is the restful web service only. But, I am not sure about it if its the same thing.
Can anyone explain please.
It sounds like you have been creating the same types of RESTful services. You may be referring to is JAX-RS with is a standard that defines an easier way of creating RESTful services where JAXB is the standard binding layer for the application/xml media type. Below is an example service:
package org.example;
import java.util.List;
import javax.ejb.*;
import javax.persistence.*;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
#Stateless
#LocalBean
#Path("/customers")
public class CustomerService {
#PersistenceContext(unitName="CustomerService",
type=PersistenceContextType.TRANSACTION)
EntityManager entityManager;
#POST
#Consumes(MediaType.APPLICATION_XML)
public void create(Customer customer) {
entityManager.persist(customer);
}
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("{id}")
public Customer read(#PathParam("id") long id) {
return entityManager.find(Customer.class, id);
}
#PUT
#Consumes(MediaType.APPLICATION_XML)
public void update(Customer customer) {
entityManager.merge(customer);
}
#DELETE
#Path("{id}")
public void delete(#PathParam("id") long id) {
Customer customer = read(id);
if(null != customer) {
entityManager.remove(customer);
}
}
}
For More Information
http://blog.bdoughan.com/2010/08/creating-restful-web-service-part-45.html
When it comes to say 'RESTful', it's just an convention of HTTP methods and url patterns.
CRUD METHOD URL RESPONSE DESCRIPTION
----------------------------------------------------------------
CREATE POST http://www.doma.in/people 202 Creates a new person with given entity body
READ GET http://www.doma.in/people 200
READ GET http://www.doma.in/people/1 200 404 Reads a single person
UPDATE PUT http://www.doma.in/people/2 204 Updates a single person with given entity body
DELETE DELETE http://www.doma.in/people/1 204 Deletes a person mapped to given id(1)
You can even implement those kind of contracts with Sevlets. Actually I had done with Sevlets before the era of JAX-RS.
And your life will be much more easier when you use JAX-RS.
Here comes a slightly modified version of Mr. Blaise Doughan's.
Nothing's wrong with Mr. Blaise Doughan's code.
I just want to add more for above url patterns.
One of great things that JAX-RS can offer is that you can serve XMLs and JSONs as clients want if you have those fine JAXB classes. See #Producess and #Consumess for those two formats in same method.
When client want to receive as XML with Accept: application/xml, they just get the XML.
When client want to receive as JSON with Accept: application/json, they just get the JSON.
#Path("/customers");
public class CustomersResource {
/**
* Reads all person units.
*/
#POST
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response read() {
final List<Customer> listed = customerBean.list();
final Customers wrapped = Customers.newInstance(listed);
return Response.ok(wrapped).build();
}
#POST
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response createCustomer(final Customer customer) {
entityManager.persist(customer);
return Response.created("/" + customer.getId()).build();
}
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Path("/{id: \\d+}")
public Response read(#PathParam("id") final long id) {
final Customer customer = entityManager.find(Customer.class, id);
if (customer == null) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok(customer).build();
}
#PUT
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public void updateCustomer(final Customer customer) {
entityManager.merge(customer);
}
#DELETE
#Path("/{id: \\d+}")
public void deleteCustomer(#PathParam("id") final long id) {
final Customer customer = entityManager.find(Customer.class, id);
if (customer != null) {
entityManager.remove(customer);
}
return Response.status(Status.NO_CONTENT).build();
}
}
Say you want to serve some images?
#GET
#Path("/{id: \\d+}")
#Produces({"image/png", "image/jpeg"})
public Response readImage(
#HeaderParam("Accept") String accept,
#PathParam("id") final long id,
#QueryParam("width") #DefaultValue("160") final int width,
#QueryParam("height") #DefaultValue("160") final int height) {
// get the image
// resize the image
// make a BufferedImage for accept(MIME type)
// rewrite it to an byte[]
return Response.ok(bytes).build();
// you can event send as a streaming outout
return Response.ok(new StreamingOutput(){...}).build();
}
I am trying to a find a good design for the following scenario.
I have a POST rest service which will be given an array of services as data. And which should in turn be calling them one by one to aggregate results on the server and send them back to the client.
#Path("/resource1")
#Path("/resource2")
#Path("/collection")
Post data to /collection
{["serviceName": "resource1", "data":"test1"], ["serviceName":"resource2","data":"test2"]}
The reason i need the resource1 and resource2 are, because those services can be called standalone also. I want to reuse the same setup if possible.
Is there any way to do this.
I am using jersey with spring.
Not sure what these resources have in common. If the post method has the same signature for all of them, you could have an abstract class or interface they implement defining the post method and can try using ResourceContext.matchResource to do this. E.g. something like this:
public abstract class AbstractResource {
public abstract String post(Object data);
}
#Path("/resource1")
public class Resource1 extends AbstractResource {
#POST
public String post(String data) {
// do something
}
}
#Path("/collection")
public class CollectionResource {
#Context
private ResourceContext rc;
#POST
#Consumes("application/json")
public String post(List<PostRequest> postRequests) {
StringBuilder result = new StringBuilder();
for (PostRequest pr : postRequests) {
// should wrap this in try-catch
AbstractResource ar = rc.matchResource(pr.resource,
AbstractResource.class);
sb.append(ar.post(pr.data));
}
return result.toString();
}
}
#XmlRootElement
public class PostRequest {
public String resource;
public String data;
}
Hopefully you got the idea and will be able to play with it and tweak it to fit your needs.