RESTful Web Services from Entity Classes - web-services

I want to implement restful web-services to query my database.
In Netbeans I did this:
- I created entity classes from my db
- I generated web-services from these entity classes
GET methods work fine when testing but I have some additional requirements. I dont want to query only by tables' id-s. Data needs to be retrieved also when some other parametres are entered.
For example I have a table:
Customer: id, name, address, country
Now I want to display all customers from a specific country.
Where in code can I achieve that?

You can do this with slightly different urls.
So for a single customer you'd present a URL such as:
GET /customer/123.html
But for multiple customers, you'd figure out a way to specify groups. If you wanted all customers, you'd go for:
GET /customers.html
But say you grouped by country, you could try:
GET /customers/Australia.html
Using the singular or plural form would separate the two types of get-requests.

Related

Redmine Custom Query to return only specific columns

How to filter Redmine issues to only include specified columns, when using the REST API xml/json format?
I have a custom query to obtain specific columns of issues:
Filter set to "status(open)" and "Due Date(any)"
Options / Selected Columns set to "Due Date" (To only return the ID and the Due Date in the response)
These are two ways of accessing it:
A /issues?query_id=myqueryid
B /issues.xml?query_id=myqueryid
When i run A in my browser, the correct response is given, containing only the id and the due date. In contrast to B, now every field (ie. id, description, start date,...) is included in the response.
I also tried to add a "fields" value as some other apis suggest, but to no avail (ie. /issues.xml?issue_id=1337&fields=due_date,etc).
Redmine's REST API (i.e. the JSON and XML APIs) always returns all base fields of filtered issues. You can optionally include additional fields like watchers, journals, issue relations, ... by using the include mechanism describe in the API docs
When using the API, the client is supposed to fetch any fields it desires from the response on their own. The feature to show a tailored HTML table with selected columns as done in the web UI is considered not very useful for the API use-case right now.

How to design Restful URIs with mapping based resources

I am using Django rest framework for writing some rest API in which I have two primary resources as Store and Product.
Now the URIs for these resources are like
List all the stores GET /stores/
List store with ID GET /stores/:id/
Add a new store POST /stores/
Update some attributes in a store PUT /stores/:id/
Same is applicable to products
List all the products GET /products/
List product with ID GET /products/:id/
Add a new product POST /products/
Update some attributes in a product PUT /products/:id/
Now i want to map some products to some stores like if store A is selling products with ID 1 to 100 and store B is selling products with ID 70 to 200.
With this i have got another resource as store_product_mappings
Now i can treat it as above and make URIs for this resource as
List all the store_product_mappings GET /store_product_mappings/
List store_product_mapping with ID GET /store_product_mappings/:id/
Add a new store_product_mapping POST /store_product_mappings/
Update some attributes in a store_product_mapping PUT /store_product_mappings/:id/
But now this mapping id isn't exposed to the consumers of this API. So in order to avoid this complexity i want to make a easilty understandable URI like
To list all the products inside a store GET /stores/:id/products/
To list a product inside a store GET /stores/:id/products/:product_id
To update a product inside a store PUT /stores/:id/products/:product_id
But according to this approach if i do post on this URI
POST /stores/:id/products/
It should create a new mapping resource and return the ID for that mapping resource, in the similar way it will expect the mapping id when i want to retrieve that resource back like
GET /stores/:id/products/:id
But i don't want to expose mapping ids as it's part of my internal system and consumers of API shouldn't need to worry about it. I am still looking for solutions for this kind of use case and resources in Django rest framework.
Let me know if someone has already faced the similar issue and with what approach they were able to implement this without violating the Rest API conventions.
This request:
POST /stores/:storeid/products/
can expose the product_id as part of the URI returned:
Location: /stores/{storeid}/products/{productid}
It does not need to tell you the technical id of the mapping row in your database. Remember, you don't have to expose database rows one-to-one in your REST API.
As a sidenote, if your clients are Hypertext driven (as they should be), they don't have to parse or construct URIs manually, therefore it would be not that important what you expose in the URIs.

Cross-service references in DB

I am building service oriented system, with multiple services and application.
Current I am not sure how to handle DB references between resources from multiple services and databases.
For example, I have a users service, where I can define all users and their roles.
Next I have, products service, where I can define my products, their prices and other information.
I also have invoicing service, which is used to create invoices. This service will use information from previous two services. It will link products and users to invoice. Now I am not sure what is the best approach for this?
Do I just save product ID and user ID that it got from other two services, without any referential integrity?
If I do this, then I will have problem when generating reports, because at time of generation I will need to send a lot of requests to products service, to get names and prices of product in invoice. Same for users.
Do I create some table products in my invoicing application, and store name and price of product at the moment of invoice creation?
If I go with this approach, then in case that price or name of product changes, I will have inconsistent data across my applications?
Is there some well-known pattern for this kind of problem, that is what is the best solution.
Cross-service references in DB is a common challenge for Data integrity between multiple web services, And specially when we are talking about Real time access.
There is two approaches for your case :
1- Databases Replication across your servers
I suppose that you have each application hosted on a separate server, So i can name your servers as Users_server, Products_server and Invoices_Server.
In your example, your Invoice web service need to grab data from Users & Products Servers, in this case you can create a Replication of your Users Database and Products Database on your Invoices_server.
This way you can run your Join queries on the same server and get data from multiple databases.
Query example :
SELECT *
FROM UsersDB.User u
JOIN InvoicesDB.Invoice i ON u.Id = i.ClientId
2- Main Database Replication
1st step you have to replicate all your databases into one main server we can call it Base_server, which basically contain all your databases from all your services.
Then you can build an internal web service for your application to provide needed data in just "One Call", this answer your question about generating reports.
In other words, you will make one call to the mane Base service instead of making 2 or 3 calls to your separate services.
Note: As a Backend developer we use this organization as a best practice while building a large bundle based application, we create a base bundle and then create service_bundle which rely on the base bundle.
If your services are already live, we may need more details about the technology and databases type you using in order to give you a more accurate solution.
Just because you are using SOA doesn't mean you abandon database integrity. Continue to use referential integrity where your database design requires it.
At the service level, you can have each service be responsible for returning identity information for the entities which it owns. This identity information may or may not be the actual primary key from the database, but it will be used by the clients of the service as though it were the actual primary key.
When a client wants to create an invoice, it will call the User service and receive a User entity, which will contain a User Identifier. It will call the Product service and receive a set of products, each with a product identifier. It will then call the Invoice service to create an invoice, passing the user identifier and the product identifiers. This will likely return an invoice identifier.
You can (probably should) enforce the integrity making the productId and userId foreign keys in your invoice table. Then your DB makes sure the referenced entities exist. Reports should join tables, not query services for each item. I assume a central DB shared across the system.

How to restrict certain rows in a Django model to a department?

This looks like it should be easy but I just can't find it.
I'm creating an application where I want to give admin site access to people from different departments. Those people will read and write the same tables, BUT they must only access rows belonging to their department! I.e. they must not see any records produced by the other departments and should be able to modify only the records from their own department. If they create a record, it should automatically "belong" to the department of the user which created it (they will create records only from the admin site).
I've found django-guardian, but it looks like an overkill - I don't really want to have arbitrary per-record permissions.
Also, the number of records will potentially be large, so any kind of front-end permission checking on a per-record basis is not suitable - it must be done by DB-side filtering. Other than that, I'm not really particular how it will be done. E.g. I'm perfectly fine with mapping departments to auth groups.

REST API with complex queries

I don't fully understand how to make complex queries with REST API on the backend, and a backbone web app on the frontend. Say I have a user table that has a relation with a user_group table:
user.group_ref => user_group.id
If I do a GET on /api/v1/user/1/?format=json it will do something like SELECT * FROM users WHERE id = 1. Right, ok, now... how about if I wanted to JOIN with my user_group where user.group_ref = user_group.id to instantly have access to the data on user_group. I don't want to do an extra query to go and fetch that data.
Maybe I got the whole idea wrong ... Is there a simpler way?
REST is a set of conventions. It doesn't provide for automatic query mapping, so you need to define a service endpoint, and then implement it to return whatever you want it to.
In your case a typical way of composing the URL would be something like:
GET /groups/(groupid)/users
Which is to say "give me all users belonging to this group". Alternatively:
GET /users?group=(groupid)
Which in style is less "RESTful", but doesn't unnecessarily promote group as a top-level resource.
Either way, Backbone doesn't provide an OOTB way for populating collections from more complex resources. For anything beyond simple CRUD you'll have to implement the service call yourself, or create a separate read-only collection with url that maps to your service. Something like:
var UserGroupCollection = Backbone.Collection.extend({
url: function() { return "groups/" + this.options.groupId + "/users"; }
});
var group = new UserGroupCollection({groupId:1});
group.fetch();
The REST API can be implemented separately, without any relationship to the front end, it can be designed as you need.
In your case, if you are always going to get the user_group.id with the query for a user, then you should change your SQL to JOIN statements permanently: SELECT * FROM users WHERE id = 1 JOIN user_group WHERE user.group_ref=user_group.id.
If you need both queries with and without user_group info. You can design two REST methods, such as (GET /api/v1/user/1?format=json) for without group info, and (GET /api/v1/userwithgroup/1?format=json) for ones with group info.
And on the Backbone, you could have two different Models representing the two.
If you don't have millions of users in the table, the SQL with group info should be quite fast and it would be easier to just always have group info with it.
There is a python library called slubmber (http://slumber.in/) which is built on top of requests for the explicit purpose of REST APIs.