This is the following code of my RESTful service class:
#RequestScoped
#Path("/empresas")
public class EmpresaEndpoint {
#Inject
private EmpresaRB empresaRB;
#GET
#Path("/{id:[0-9][0-9]*}")
#Produces("application/json")
public Response findById(#PathParam("id") final Long id) {
//TODO: retrieve the empresas
Empresa empresas = null;
if (empresas == null) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok(empresas).build();
}
#GET
#Produces("application/json")
public List<Empresa> listAll(
#QueryParam("start") final Integer startPosition,
#QueryParam("max") final Integer maxResult) {
//TODO: retrieve the empresa
return empresaRB.getEmpresas();
}
}
If I wanted to access all the data stored on "Empresa" via jQuery, I would do:
$.getJSON( "rest/empresas", function( data ) {
//whatever is needed.
}
The code above would access the "listAll" method. So how can I access the "findById" method and pass the necessary parameter?
Assuming you have a variable called empresaId that holds the id for the entity, this should work.
$.getJSON( "rest/empresas/" + empresaId, function(data) {
// Whatever is required here
}
Well without having used that particular framework, it looks like it's mapping to the right method based on the path - it will use findById if the path has an ID, e.g.
$.getJSON("rest/empresas/100", function(data) {
// ...
}
(That will find the item with ID 100... obviously substitute the ID of the item you want to find. We don't know where that's coming from, but "rest/empresas/" + id may well be all you need.)
In my initial code, there was no query being connected to the variable "empresa", on the method findById().
I created a query on the repository class and assigned it to the variable. Problem Solved.
Thank you all for the time lended.
Related
I have an objects in java backend that i want to change status property on:
#Entity
public class Employee {
#Id #GeneratedValue long id;
private String name;
private String status;
}
I want to set the property status to "Checked" for a targeted object chosen with id with this putmapping:
#PutMapping("/api/users/id")
public Employee changeStatus(#RequestParam Long id)
{
Employee newEmployee = userRepository.getById(id);
newEmployee.setStatus("Checked");
return userRepository.save(newEmployee);
}
I want to do it from my frontend through :
public changeStatus(id: number): Observable<any>
{
return this.http.put<any>(${this.apiServerUrl}/users/id, id)
}
Nothing happens in backend, no errors or anything shows up. What am i missing? I suspect i do something wrong in the frontend call, but i cant figure it out.
Backend-frontend connections seems to work because i can get all data from my backend and see it in frontend with theese two endpoints
Backend:
#RequestMapping("/api/users") public List<Employee> getUsers()
{
return (List<Employee>) userRepository.findAll();
}
Frontend:
public getUsers(): Observable<any>
{
return this.http.get<any>(${this.apiServerUrl}/users)
}
Thanks in advance!
Are you subscribing to this call on the FE ? the angular HttpClient returns an Observable, if you are not subscribing, i.e. if you are not doing something like this:
getUsers().subscribe((data) => {
console.log('whatever');
})
The http request will never be send, that's how observable works, they only get "executed" when someone is "listening"
Seeing how you try to pass id as pathVariable your endpoint should also accept it as such. For that refactor your endpoint. Frontend looks fine.
#PutMapping("/api/users/{id}")
public Employee changeStatus(#PathVariable Long id)
{
Employee newEmployee = userRepository.getById(id);
newEmployee.setStatus("Checked");
return userRepository.save(newEmployee);
}
Remove one extra id from url.
public changeStatus(id: number): Observable<any>
{
const url = this.apiServerUrl + /users/ + id;
return this.http.put<any>(url);
}
Otherwise try to get rid of any types and use strong typing - that's the benefit TypeScript gives us.
what I am trying to do is,
If I take one pojo class like
#Entity
#Table(name = "property_table")
public class Property {
#Id
#Column(name = "property_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int propertyId;
#Column(name = "property_name")
private String propertyName;
#Column(name = "property_type")
private String propertyType;
}
In RestController I wrote Two Methods like
#GetMapping(value = "/getProperties", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
#ResponseBody
public List<Property> getProperties() {
//some code
}
#GetMapping(value = "/getPropertyById", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
#ResponseBody
public Property getPropertyById() {
//some code
}
So, hear what I am trying to do is
for first api method I want return json like some parameters from Property pojo class i.e., like
for getProperties api method
{
"property":[
{
"propertyId":001,
"propertyName":"PROPERTY 1"
},
{
"propertyId":002,
"propertyName":"PROPERTY 2"
}
],
In the Above json I want to return only two parameters i.e propertyId,propertyName and remaining parameter i.e propertyType I dont want to retun in json.
How to return like that?
and for the second api method I want to return all three parameters. i.e., like below
for getPropertyById api method
{
"propertyId":001,
"propertyName":"PROPERTY 1",
"propertyType:"PROPERTY_TYPE 1"
},
how to maintain different json response using same pojo class with different parameters for different api methods.
please help me to solve this isuue.
Thanks.
REST API under/over-fetching is a well-known problem. There's only two (classical ways) to handle that.
The first one is to build one model per each attribute visibility state. So, in your case, you'll need to create two different models (this kind of models are called DTO - Data Transfert Object). One model will have a propertyType attribute, the other will not. The model Property you've shared shows that you use the same class as entity and as transfert object. This solution will add some complexity to your app because you will have to implement some mappers to convert your entity to a corresponding DTO.
The second one is to accept that you send an attribute that will not be useful (be aware of the over-fetching). This solution is often the most adopted one. The cons of this solution is when you don't want to send something to your client (imagine a User model, you want to get the password from your client but you don't want to sent it back to it). Another obvious negative point is that the transactions will be larger but it is negligible in most cases
I would strongly advice you to keep your #Entity isolated in the 'db' layer. So that changes on the database side don't affect your API and vice versa. Also, you will have much better control over what data is exposed in your API. For your needs you can create 2 true DTOs, like PropertyDto and PropertyDetailsDto (or using private fields and getters/setters).
public class PropertyDto {
public String propertyId;
public String propertyName;
}
public class PropertyDetailsDto extends PropertyDto {
public String propertyType;
}
Map your #Entity to a specific dto corresponding to your needs.
EDIT
public List<PropertyDto> getProperties() {
return toPropertyDtos(repository.findAll());
}
public PropertyDetailsDto getPropertyById(Long id) {
return toPropertyDetailsDto(repository.findBy(id));
}
in some Mapper.java
...
public static List<PropertyDto> toPropertyDtos(List<Property> properties) {
return properties.stream()
.map(Mapper::toPropertyDto)
.collect(toList());
}
private static PropertyDto toPropertyDto(Property property) {
PropertyDto dto = new PropertyDto();
dto.propertyId = property.propertyId;
dto.propertyName = property.propertyName;
return dto;
}
// same stuff for `toPropertyDetailsDto`, you could extract common mapping parts in a separate private method inside `Mapper`
...
I using postman and spring boot. In spring boot i using code look like :
public PersistableCategory createCategory(#RequestBody PersistableCategory persistableCategory, MerchantStore store, HttpServletRequest httpRequest) {
MerchantStore merchantStore = (MerchantStore) httpRequest.getAttribute("MERCHANT_STORE");
return categoryService.saveCategories(store,persistableCategory);
}
get attribute from httpservletrequest. But i can't know where i set attribute with name MERCHANT_STORE in postman. I set in body look like
{
"attributes": {
"MERCHANT_STORE": {
"code":"1"
}
},
but it not working. How to set attribute in postman and using HttpServletRequest get it.
if you have more APIs, and need to response like the request (more than one depth attribute)
{
"attributes": {
"MERCHANT_STORE": {
"code":"1",
"code2":{
"element1":"1",
"element2":"2"
}}}
2.First, make a class for response.
public class responseData {
private merchant_store;
// getter, setter, the other elements..
}
i think that's better to make to make class for setting results.
public class result{
private View json; // this object from spring servlet lib.
// and make methods to parse http header(yep, in postman) and to return datas.
}
Let's make response in controller.
public PersistableCategory createCategory(){
MerchantStore merchantStore = (MerchantStore);
httpRequest.getAttribute("MERCHANT_STORE");
Object purpose = categoryService.saveCategories(store,persistableCategory);
Object responseData = new responseData();
responseData.set(purpose);
result.set(responseData, successYn);
return result;
}
Well, successYn is just String in my
Because i wanted to know whether it finished to access DB and set Datas.
if you want you can set other types.
I'm creating a Java application using Elastic Search.
Here is the link for my project.
https://github.com/chanakaDe/ensembl-elastic-rest
In this project, I have implemented a rest controller to take data as JSON.
This is the controller class. Now it only has 2 methods. But I need to add some method like this.
#RequestMapping(value = "/find-by/{id}/{param1}/{param2}/{param3}", method = RequestMethod.GET)
public Iterable<Track> findAllWithParams(#PathVariable int id, #PathVariable String param1, #PathVariable String param2, #PathVariable String param3) {
return trackService.someMethodWithParams(id, param1, param2, param3);
}
What I need to do is take some values from user and send them into Elastic server and make a search. I just refered some of these links and got some idea.
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-search.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html
TrackService.java and TrackServiceImpl.java are implemented by TrackRepository.java and it's extended by ElasticsearchRepository default class. https://github.com/chanakaDe/ensembl-elastic-rest/blob/master/src/main/java/com/chanaka/book/repository/TrackRepository.java
I need to take values via REST URL and create an object like following and pass that to Elastic Server. How can I implement that with my current project configuration ?
{
"query": {
"constant_score" : {
"filter" : {
"terms" : { "user" : ["kimchy", "elasticsearch"]}
}
}
}
}
This is my TrackService.java interface.
public interface TrackService {
Track save(Track track);
Track findOne(int id);
Iterable<Track> findAll();
}
And also this is my TrackServiceImpl.java class implemented by TrackService.java.
public class TrackServiceImpl implements TrackService {
private TrackRepository trackRepository;
#Autowired
public void setTrackRepository(TrackRepository trackRepository) {this.trackRepository = trackRepository;}
#Override
public Track save(Track track) {
return trackRepository.save(track);
}
#Override
public Track findOne(int id) {
return trackRepository.findOne(id + "");
}
#Override
public Iterable<Track> findAll() {
return trackRepository.findAll();
}
}
Do I need to implement a custom method for that ? Or is there any default methods like findAll() and findOne() ?
Simply pass an object and get the value ?
I think, there's no such existing method and you need to create your own by using QueryBuilders.wrapperQuery(query.toString()) and ElasticsearchTemplate. Just to note, wrapperQuery supports only query not filter. But you can achieve filter context query with constant_score.
I have a web service that looks like:
#Path("/ws")
public class Ws {
#GET public Record getOne(#QueryParam("id") Integer id) { return record(id); }
#GET public List<Record> getAll() { return allRecords(); }
}
The idea is that I can either call:
http://ws:8080/ws?id=1 to get a specific record
http://ws:8080/ws to get all available records
However when I use the second URL, the first #GET method is called with a null id.
Is there a way to achieve what I want without using different paths?
I think this can be achieved with Spring using the #RequestMapping(params={"id"}) and #RequestMapping annotations for the first and second methods respectively but I can't use Spring in that project.
Since the path is the same, you cannot map it to a different method. If you change the path using REST style mapping
#Path("/ws")
public class Ws {
#GET #Path("/{id}") public Response getOne(#PathParam("id") Integer id) { return Response.status(200).entity(record(id)).build(); }
#GET public Response getAll() { return Response.status(200).entity(allRecords()).build(); }
then you should use:
http://ws:8080/ws/1 to get a specific record
http://ws:8080/ws to get all available records