I am learning Spring Boot, I have managed to deploy an API on my computer which fetches data from Oracle and when I paste the link http://localhost:8080/myapi/ver1/table1data in browser it returns me the data. Below is my controller code :
#CrossOrigin(origins = "http://localhost:8080")
#RestController
#RequestMapping("/myapi/ver1")
public class Table1Controller {
#Autowired
private ITable1Repository table1Repository;
#GetMapping("/table1data")
public List<Table1Entity> getAllTable1Data() {
return table1Repository.findAll();
}
Now this scenario is working fine. I want to do another thing. There is an API https://services.odata.org/V3/Northwind/Northwind.svc/Customers which returns some customers data. Does spring boot provide any way so that I can re-host/re-deploy this API from my own controller such that instead of hitting this the above link in the browser, I should hit http://localhost:8080/myapi/ver1/table1data and it will return me the same customers data.
Yes the spring boot provides a way to hit an external URL from your app via a RestTemplate. Below is a sample implementation of getting the response as string or you can also use a data structure of desired choice depending on the response,
#RestController
#RequestMapping("/myapi/ver1")
public class Table1Controller {
#Autowired
private RestTemplate restTemplate;
#GetMapping("/table1data")
public String getFromUrl() throws JsonProcessingException {
return restTemplate.getForObject("https://services.odata.org/V3/Northwind/Northwind.svc/Customers",
String.class);
}
}
You can create a config class to define the Bean for the rest controller. Below is the snippet,
#Configuration
public class ApplicationConfig{
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
You can use RestTemplate for third party API call and return the response from your API
final String uri = "https://services.odata.org/V3/Northwind/Northwind.svc/Customers";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
This website has some nice examples for using spring's RestTemplate
Create a #Bean of RestTemplate
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
By using the above RestTemplate you can fetch the data from ur own localhost
String url = "https://services.odata.org/V3/Northwind/Northwind.svc/Customers";
restTemplate.getForObject(url,String.class);
Related
I need some assistance on the correct way to POST a json body with RestTemplate within a RestController. I am just not familiar enough as to what I am doing wrong. I have spent to much time looking at this and I am not getting the result I need. Hopefully the info I provide is clear. As of right now I am just trying to POST the JSON body to the below URL API
CONTROLLER
#RestController
#RequestMapping("/api/feedback")
public class FeedbackController {
private final RestTemplate restTemplate;
#Autowired
public FeedbackController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
#RequestMapping(
method = RequestMethod.POST
)
public IncidentReport createIncident()
{
return restTemplate.exchange(
"URL_API/create",
HttpMethod.POST, null,
new ParameterizedTypeReference<IncidentReport>(){}
).getBody();
}
JSON POST BODY
{
"group": "my_group",
"short_description":"this is a test for the short description",
"contact_type":"Alert",
}
exchange is the low-level method, and the more specific ones are usually more friendly as long as they cover your use case. You're looking for a postForObject (postForEntity if you need the headers):
return restTemplate.postForObject(url, incidentObject, IncidentReport.class);
StackTrace would have been more helpful. I think you should instantiate RestTemplate in below manner.
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(3000))
.setReadTimeout(Duration.ofMillis(3000))
.build();
}
Then AutoWire it in your Controller class
#Autowired
private RestTemplate myRestTemplate;
Ensure Jackson library is present in the classpath. Try to use myRestTemplate.postForObject(). There is not much to this. If you are still getting an issue try to analyze stack trace, you will get some hint.
Since spring boot autoconfigures RestTemplate and ObjectMapper to serialize/deserialize in your #RestController endpoints you don't have to stick with RestTemplate at all and can use functionality as show in the following code snippet:
#RestController
#RequestMapping("/api/feedback")
public class FeedbackController {
#Autowired private FeedbackFacade feedbackFacade;
#PostMapping("/")
public ResponseEntity<IncidentReport> createIncidentReport(
#RequestBody IncidentReport incidentReport)
{
log.info("Create incident report {}", incidentReport);
var createdIncidentReport = feedbackFacade.create(incidentReport);
log.info("Created incident report: {}", createdIncidentReport);
return new ResponseEntity<>(createdIncidentReport, HttpStatus.CREATED)
}
}
With AngularJS, I knew that Spring Boot can use model.attribute to return many objects or list object same below:
#Controller
public class TestController {
private Logger logger = LoggerFactory.getLogger(getClass());
#RequestMapping(value="/hello")
public String home(HttpServletRequest httpRequest, Model model) {
model.addAttribute("Authorization", "test string");
return "/index";
}
}
But don't know how to make the same in Spring Boot and Angular 8???
Spring Boot + Angular 8 and Spring Boot + AngularJS are the same?
Anyone can help me??? Thank you?
When you using angular then you get JSON response when to do HTTP request so please try this,
and Also add Cross Origin at your rest controller to communication between cross-server
#RestController
public class TestController {
private Logger logger = LoggerFactory.getLogger(getClass());
#RequestMapping(value="/hello")
public PayloadRespons home(HttpServletRequest httpRequest, Model model) {
PayloadRespons payload = new PayloadRespons();
payload.setAuthorization = "test string"
// model.addAttribute("Authorization", "test string");
return payload;
}
}
class PayloadRespons{
private String Authorization;
.... some more which you have
.... Getter and Settter
}
I need to mock a service. i m getting null in ResponseEntity<?> resp while mocking the class.
Method which need to mock:
public List<Expression> getExpression(String expressView, Localdate date) {
List<Expression> =new ArrayList<>();
Map<String, Object> uri = new HashMap<>();
UriComponenetsBuilder build =
UriComponentsBuilder.fromHttpUrl("someUrl" + "/" + expressView);
build.queryParam(someParameter, someParameter);
build.queryParam(someParameter, someParameter);
build.queryParam(someParameter, someParameter);
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
RestClient client = new RestClient(
build.build().encode.toUriString, HttpMethod.GET.Uri, header
);
ResponseEntity<?> resp = restC.SomeMethod(client);
if (resp = !null) {
//it goes to these line
}
}
In my mock method:
when(restC.SomeMethod(client)).thenReturn(resp);
So above method call a service get some data get the value of expressView and save as list. when i mocked the method when(restC.SomeMethod(client)).thenReturn(resp); it hit the URL but the value i m getting as response resp is null .
So here i m getting the resp value as null. I checked the URL(someUrl) in postman its returning the value.
How to mock the ResponseEntity<?>?
Thanks.
First, create a ResponseEntity object:
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
ResponseEntity<?> responseEntity = new ResponseEntity<>(
"some response body",
header,
HttpStatus.OK
);
Then build a mock to return the responseEntity object:
when(restC.SomeMethod(client)).thenReturn(responseEntity);
Point to pay attention:
Avoid to use ResponseEntity inside #Service class. You should use ResponseEntity in #RestController class.
And you can Inject your #Service class using #Autowired annotation, like:
#RestController
public class YourControllerClass {
#Autowired
private YourServiceClass yourServiceClass;
Or using constructor, like:
#RestController
public class YourControllerClass {
private YourServiceClass yourServiceClass;
public YourControllerClass(YourServiceClass yourServiceClass) {
this.yourServiceClass= yourServiceClass;
}
So:
#Service class will handle business or data objects and #RestController class will handle Response and Request objects. Thus we have Single Responsibility principle.
Some nice links:
Spring MVC - Using RequestEntity and ResponseEntity
How do I mock a REST template
Building REST services with Spring
Understanding the Single Responsibility Principle
Hope this helps!
I have created a microservice with an endpoint of
http://www.example.com/create which makes a post request. In this request, I make use of ResponseEntity class i.e.
#PostMapping("/create")
public ResponseEntity<?> createUser(#RequestBody User user) {
//do some other stuff i.e. validation
someService.createUser(user);
URI location = ...;
return ResponseEntity.created(location).build();
}
Now I want to call the post request /create from another application i.e. whilst accessing http://www.example-2.com/signup call /create to create user entity.
#PostMapping("/signup")
public ModelAndView createUser(#Valid UserForm form) {
//How do I make `/create` post request to post
//the `form` entity
return new ModelAndView("some view");
}
Use Spring RestTemplate. Here is tutorial example on how to use it. You can just create a singleton bean of RestTemplate and autowire in the controller class and use it to make the rest call.
String response = restTemplate.postForObject("https://your-domain/create",user, String.class)
In my Spring Boot web application I have a JPA entity Medium that records information about uploaded files.
I have a basic Spring Data Rest repository to handle the generic operations:
#RepositoryRestResource(path = "/media")
public interface MediumRepository extends CrudRepository<Medium, Long> {
}
However, I need the client to upload a file using HTTP multipart upload, then create a Medium record and return it in the response. The structure of the response should be the same as calling repository.save(). What I cannot figure out is how to have the HATEOAS metadata added. Obviously, if I just return
return mediumRepository.save(medium);
it will return a basic JSON representation of the entity, no HATEOAS. I already learned that I should probably use a PersistentEntityResourceAssembler.
So, my current controller code is:
#RestController
#RequestMapping("/upload")
public class MediaEndpoint {
#Autowired
private MediumRepository mediumRepository;
#RequestMapping(method = POST)
public PersistentEntityResource uploadMedium(
#RequestPart MultipartFile data,
PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
Medium medium = new Medium();
// setup of the medium instance
Medium savedMedium = mediumRepository.save(medium);
return persistentEntityResourceAssembler.toResource(savedMedium);
}
}
However, I cannot get the persistentEntityResourceAssembler injected into the method - I'm getting
Failed to instantiate [org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.<init>()
How can I implement this?
Following Cepr0's answer, I changed my controller to a #RepositoryRestController, but I got an exception
Circular view path [upload]: would dispatch back to the current handler URL [/upload] again.
Check your ViewResolver setup! (Hint: This may be the result of an unspecified view,
due to default view name generation.)
I found that RepositoryRestControllers are not annotated with #ResponseBody and should return a ResponseEntity, so I changed my code to the following:
#RepositoryRestController
#RequestMapping("/upload")
public class MediaEndpoint {
#Autowired
private MediumRepository mediumRepository;
#RequestMapping(method = POST)
public ResponseEntity<PersistentEntityResource> uploadMedium(
#RequestPart MultipartFile data,
PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
Medium medium = new Medium();
// setup of the medium instance
Medium savedMedium = mediumRepository.save(medium);
return ResponseEntity.ok(persistentEntityResourceAssembler.toResource(savedMedium));
}
}
This gives me a nice JSON response with HATEOAS metadata.
Alternatively, annotating the method or the controller with #ResponseBody works the same way.
Try to use #RepositoryRestController instead of #RestController.