Querying FHIR resrouces using JSON and Java - java

I'm trying to figure out a basic approach to querying FHIR resources. My first task is to query using a REST interface. Using the information on the Search page, I see there are 7 search parameter types (NUMBER, DATE, STRING, TOKEN, REFERENCE, COMPOSITE, QUANTITY). My question is:
How does one determine a parameter's type when it's passed to the server in a URL's query string?
Since modifiers like :exact and :token only apply to certain parameter types, it seems important to identify the type of each parameter in the query string. I'm hoping the server is not expected to look up parameter types based on the resource being queried.
I'm using FHIR 0.81 with Java and JSON.
Thanks,
Rich

The server does need to look up the parameter types depending on the resource being queried. The server has to actually recognise the parameters to do anything with them anyway.
(and I assume you mean 0.0.81)

Related

How to accept multiple query parameters with different parameter name in one class

Consider a use case where I have a URL like
/api/v1?credentials="test"&age=20&gender=male
Now how can I have 2 different type of cases
USE CASE-1
How can I accept the above query parameters in the form a class from swagger, I know we can define this in swagger as different individual parameters something like this
parameters:
- in: query
name: credentials
schema:
type: string
- in: query
name: age
schema:
type: integer
- in: query
name: gender
schema:
type: string
but with this swagger creates a rest method with string or integer parameters, and having so many multiple parameters might not be a good idea so what I strongly expect is that it creates a class something like shown below, and my rest methods are generated with this class object.
And how can I leverage this class into my controller layer?
class Query{
String name;
Integer age;
String gender;
}
USE CASE-2
Is there some way I can accept all these query params into the form of a hashMap or multiValueMap
I know there is another integer in the above url query params, but for now, lets consider I will accept all these params into the form of a string and will later typecast them as per my requirement.
NOTE - that I don't want the same name parameter with multiple values, I am expecting all the query parameters with or without the same names to be mapped into one string-to-string key-value pair.
So let's say when I had to access them I will directly use something like map.get("age")
To have these parameters as query parameters is just fine according to REST. Your controller method to handle the request will be good accepting 3 values as int or Strings. For logging in, a better choice would be to use POST method, depending on what you wish to achieve.
From your example, you really should check state-of-the-art authentication. You could consider JWT, it can wrap all these values securely and is actually designed for doing this. After you log-in a user with credentials, the JWT will be created and can then be used by the client for succeeding interactions as long as it is valid.
Edit:
The Swagger notation also supports a deepObject notation as suggested in https://swagger.io/docs/specification/describing-parameters/, which indeed is not exactly what you are looking for. Still, it would allow to send query accordingly: /api/v1?query[credentials]="test"&query[age]=20&query[gender]=male
In Swagger codegen, you could still consider your own code-generator that extends the basic capabilities.

javax pathparam is being ignored [duplicate]

I am not asking the question that is already asked here:
What is the difference between #PathParam and #QueryParam
This is a "best practices" or convention question.
When would you use #PathParam vs #QueryParam.
What I can think of that the decision might be using the two to differentiate the information pattern. Let me illustrate below my LTPO - less than perfect observation.
PathParam use could be reserved for information category, which would fall nicely into a branch of an information tree. PathParam could be used to drill down to entity class hierarchy.
Whereas, QueryParam could be reserved for specifying attributes to locate the instance of a class.
For example,
/Vehicle/Car?registration=123
/House/Colonial?region=newengland
/category?instance
#GET
#Path("/employee/{dept}")
Patient getEmployee(#PathParam("dept")Long dept, #QueryParam("id")Long id) ;
vs /category/instance
#GET
#Path("/employee/{dept}/{id}")
Patient getEmployee(#PathParam("dept")Long dept, #PathParam("id")Long id) ;
vs ?category+instance
#GET
#Path("/employee")
Patient getEmployee(#QueryParam("dept")Long dept, #QueryParam("id")Long id) ;
I don't think there is a standard convention of doing it. Is there? However, I would like to hear of how people use PathParam vs QueryParam to differentiate their information like I exemplified above. I would also love to hear the reason behind the practice.
REST may not be a standard as such, but reading up on general REST documentation and blog posts should give you some guidelines for a good way to structure API URLs. Most rest APIs tend to only have resource names and resource IDs in the path. Such as:
/departments/{dept}/employees/{id}
Some REST APIs use query strings for filtering, pagination and sorting, but Since REST isn't a strict standard I'd recommend checking some REST APIs out there such as github and stackoverflow and see what could work well for your use case.
I'd recommend putting any required parameters in the path, and any optional parameters should certainly be query string parameters. Putting optional parameters in the path will end up getting really messy when trying to write URL handlers that match different combinations.
This is what I do.
If there is a scenario to retrieve a record based on id, for example you need to get the details of the employee whose id is 15, then you can have resource with #PathParam.
GET /employee/{id}
If there is a scenario where you need to get the details of all employees but only 10 at a time, you may use query param
GET /employee?start=1&size=10
This says that starting employee id 1 get ten records.
To summarize, use #PathParam for retrieval based on id. User #QueryParam for filter or if you have any fixed list of options that user can pass.
I think that if the parameter identifies a specific entity you should use a path variable. For example, to get all the posts on my blog I request
GET: myserver.com/myblog/posts
to get the post with id = 123, I would request
GET: myserver.com/myblog/posts/123
but to filter my list of posts, and get all posts since Jan 1, 2013, I would request
GET: myserver.com/myblog/posts?since=2013-01-01
In the first example "posts" identifies a specific entity (the entire collection of blog posts). In the second example, "123" also represents a specific entity (a single blog post). But in the last example, the parameter "since=2013-01-01" is a request to filter the posts collection not a specific entity. Pagination and ordering would be another good example, i.e.
GET: myserver.com/myblog/posts?page=2&order=backward
Hope that helps. :-)
I personally used the approach of "if it makes sense for the user to bookmark a URLwhich includes these parameters then use PathParam".
For instance, if the URL for a user profile includes some profile id parameter, since this can be bookmarked by the user and/or emailed around, I would include that profile id as a path parameter. Also, another considerent to this is that the page denoted by the URL which includes the path param doesn't change -- the user will set up his/her profile, save it, and then unlikely to change that much from there on; this means webcrawlers/search engines/browsers/etc can cache this page nicely based on the path.
If a parameter passed in the URL is likely to change the page layout/content then I'd use that as a queryparam. For instance, if the profile URL supports a parameter which specifies whether to show the user email or not, I would consider that to be a query param. (I know, arguably, you could say that the &noemail=1 or whatever parameter it is can be used as a path param and generates 2 separate pages -- one with the email on it, one without it -- but logically that's not the case: it is still the same page with or without certain attributes shown.
Hope this helps -- I appreciate the explanation might be a bit fuzzy :)
You can use query parameters for filtering and path parameters for grouping. The following link has good info on this When to use pathParams or QueryParams
Before talking about QueryParam & PathParam. Let's first understand the URL & its components. URL consists of endpoint + resource + queryParam/ PathParam.
For Example,
URL: https://app.orderservice.com/order?order=12345678
or
URL: https://app.orderservice.com/orders/12345678
where
endpoint: https://app.orderservice.com
resource: orders
queryParam: order=12345678
PathParam: 12345678
#QueryParam:
QueryParam is used when the requirement is to filter the request based on certain criteria/criterias. The criteria is specified with ? after the resource in URL. Multiple filter criterias can be specified in the queryParam by using & symbol.
For Example:
https://app.orderservice.com/orders?order=12345678 & customername=X
#PathParam:
PathParam is used when the requirement is to select the particular order based on guid/id. PathParam is the part of the resource in URL.
For Example:
https://app.orderservice.com/orders/12345678
It's a very interesting question.
You can use both of them, there's not any strict rule about this subject, but using URI path variables has some advantages:
Cache:
Most of the web cache services on the internet don't cache GET request when they contains query parameters.
They do that because there are a lot of RPC systems using GET requests to change data in the server (fail!! Get must be a safe method)
But if you use path variables, all of this services can cache your GET requests.
Hierarchy:
The path variables can represent hierarchy:
/City/Street/Place
It gives the user more information about the structure of the data.
But if your data doesn't have any hierarchy relation you can still use Path variables, using comma or semi-colon:
/City/longitude,latitude
As a rule, use comma when the ordering of the parameters matter, use semi-colon when the ordering doesn't matter:
/IconGenerator/red;blue;green
Apart of those reasons, there are some cases when it's very common to use query string variables:
When you need the browser to automatically put HTML form variables into the URI
When you are dealing with algorithm. For example the google engine use query strings:
http:// www.google.com/search?q=rest
To sum up, there's not any strong reason to use one of this methods but whenever you can, use URI variables.
From Wikipedia: Uniform Resource Locator
A path, which contains data, usually organized in hierarchical form, that appears as a sequence of segments separated by slashes.
An optional query, separated from the preceding part by a question mark (?), containing a query string of non-hierarchical data.
— According with the conceptual design of the URL, we might implement a PathParam for hierarchical data/directives/locator components, or implement a QueryParam when the data are not hierarchical. This makes sense because paths are naturally ordered, whereas queries contain variables which may be ordered arbitrarily (unordered variable/value pairs).
A previous commenter wrote,
I think that if the parameter identifies a specific entity you should use a path variable.
Another wrote,
Use #PathParam for retrieval based on id. User #QueryParam for filter or if you have any fixed list of options that user can pass.
Another,
I'd recommend putting any required parameters in the path, and any optional parameters should certainly be query string parameters.
— However, one might implement a flexible, non-hierarchical system for identifying specific entities! One might have multiple unique indexes on an SQL table, and allow entities to be identified using any combination of fields that comprise a unique index! Different combinations (perhaps also ordered differently), might be used for links from various related entities (referrers). In this case, we might be dealing with non-hierarchical data, used to identify individual entities — or in other cases, might only specify certain variables/fields — certain components of unique indexes — and retrieve a list/set of records. In such cases, it might be easier, more logical and reasonable to implement the URLs as QueryParams!
Could a long hexadecimal string dilute/diminish the value of keywords in the rest of the path? It might be worth considering the potential SEO implications of placing variables/values in the path, or in the query, and the human-interface implications of whether we want users to be able to traverse/explore the hierarchy of URLs by editing the contents of the address bar. My 404 Not Found page uses SSI variables to automatically redirect broken URLs to their parent! Search robots might also traverse the path hierarchy.
On the other hand, personally, when I share URLs on social media, I manually strip out any private unique identifiers — typically by truncating the query from the URL, leaving only the path: in this case, there is some utility in placing unique identifiers in the path rather than in the query. Whether we want to facilitate the use of path components as a crude user-interface, perhaps depends on whether the data/components are human-readable or not. The question of human-readability relates somewhat to the question of hierarchy: often, data that may be expressed as human-readable keywords are also hierarchical; while hierarchical data may often be expressed as human-readable keywords. (Search engines themselves might be defined as augmenting the use of URLs as a user-interface.) Hierarchies of keywords or directives might not be strictly ordered, but they are usually close enough that we can cover alternative cases in the path, and label one option as the "canonical" case.
There are fundamentally several kinds of questions we might answer with the URL for each request:
What kind of record/ thing are we requesting/ serving?
Which one(s) are we interested in?
How do we want to present the information/ records?
Q1 is almost certainly best covered by the path, or by PathParams.
Q3 (which is probably controlled via a set of arbitrarily ordered optional parameters and default values); is almost certainly best covered by QueryParams.
Q2: It depends…
PATH PARAMETER -
Path Parameter is a variable in URL path that helps to point some specific resource.
Example - https://sitename.com/questions/115
Here, if 115 is a path parameter it can be changed with other valid number to fetch/point to some other resource on the same application.
QUERY PARAMETER -
Query Parameters are variables in URL path that filter some particular resources from the list.
Example - https://sitename.com/questions/115?qp1=val1&qp2=val2&qp3=val3
Here qp1, qp2 and qp3 are Query Variables with their values as val1, val2 and val3. These can be used to apply as filters while fetching/saving our data. Query variables are always appended in URL after a question Mark(?).
As theon noted, REST is not a standard. However, if you are looking to implement a standards based URI convention, you might consider the oData URI convention. Ver 4 has been approved as an OASIS standard and libraries exists for oData for various languages including Java via Apache Olingo. Don't let the fact that it's a spawn from Microsoft put you off since it's gained support from other industry player's as well, which include Red Hat, Citrix, IBM, Blackberry, Drupal, Netflix Facebook and SAP
More adopters are listed here
You can support both query parameters and path parameters, e.g., in the case of aggregation of resources -- when the collection of sub-resources makes sense on its own.
/departments/{id}/employees
/employees?dept=id
Query parameters can support hierarchical and non-hierarchical subsetting; path parameters are hierarchical only.
Resources can exhibit multiple hierarchies. Support short paths if you will be querying broad sub-collections that cross hierarchical boundaries.
/inventory?make=toyota&model=corolla
/inventory?year=2014
Use query parameters to combine orthogonal hierarchies.
/inventory/makes/toyota/models/corolla?year=2014
/inventory/years/2014?make=toyota&model=corolla
/inventory?make=toyota&model=corolla&year=2014
Use only path parameters in the case of composition -- when a resource doesn't make sense divorced from its parent, and the global collection of all children is not a useful resource in itself.
/words/{id}/definitions
/definitions?word=id // not useful
I prefer following :
#PathParam
When it's required parameters such as ID, productNo
GET /user/details/{ID}
GET /products/{company}/{productNo}
#QueryParam
When you need to pass optional parameters such as filters, online state and They can be null
GET /user/list?country=USA&status=online
GET /products/list?sort=ASC
When Used both
GET /products/{company}/list?sort=ASC
The reason is actually very simple. When using a query parameter you can take in characters such as "/" and your client does not need to html encode them. There are other reasons but that is a simple example. As for when to use a path variable. I would say whenever you are dealing with ids or if the path variable is a direction for a query.
I am giving one exapmle to undersand when do we use #Queryparam and #pathparam
For example I am taking one resouce is carResource class
If you want to make the inputs of your resouce method manadatory then use the param type as #pathaparam, if the inputs of your resource method should be optional then keep that param type as #QueryParam param
#Path("/car")
class CarResource
{
#Get
#produces("text/plain")
#Path("/search/{carmodel}")
public String getCarSearch(#PathParam("carmodel")String model,#QueryParam("carcolor")String color) {
//logic for getting cars based on carmodel and color
-----
return cars
}
}
For this resouce pass the request
req uri ://address:2020/carWeb/car/search/swift?carcolor=red
If you give req like this the resouce will gives the based car model and color
req uri://address:2020/carWeb/car/search/swift
If you give req like this the resoce method will display only swift model based car
req://address:2020/carWeb/car/search?carcolor=red
If you give like this we will get ResourceNotFound exception because in the car resouce class I declared carmodel as #pathPram that is you must and should give the carmodel as reQ uri otherwise it will not pass the req to resouce but if you don't pass the color also it will pass the req to resource why because the color is #quetyParam it is optional in req.
#QueryParam can be conveniently used with the Default Value annotation so that you can avoid a null pointer exception if no query parameter is passed.
When you want to parse query parameters from a GET request, you can simply define respective parameter to the method that will handle the GET request and annotate them with #QueryParam annotation
#PathParam extracts the URI values and matches to #Path. And hence gets the input parameter.
2.1 #PathParam can be more than one and is set to methods arguments
#Path("/rest")
public class Abc {
#GET
#Path("/msg/{p0}/{p1}")
#Produces("text/plain")
public String add(#PathParam("p0") Integer param1, #PathParam("p1") Integer param2 )
{
return String.valueOf(param1+param2);
}
}
In the above example,
http://localhost:8080/Restr/rest/msg/{p0}/{p1},
p0 matches param1 and p1 matches param2. So for the URI
http://localhost:8080/Restr/rest/msg/4/6,
we get the result 10.
In REST Service, JAX-RS provides #QueryParam and #FormParam both for accepting data from HTTP request. An HTTP form can be submitted by different methods like GET and POST.
#QueryParam : Accepts GET request and reads data from query string.
#FormParam: Accepts POST request and fetches data from HTML form or any request of the media
In nutshell,
#Pathparam works for value passing through both Resources and Query String
/user/1
/user?id=1
#Queryparam works for value passing only Query String
/user?id=1
For resource names and IDs, I use #PathParams. For optional variables, I use #QueryParams
As per my understanding:
Use #PathParam - when it is a mandatory item such as an Id
GET /balloon/{id}
Use #QueryParam - when you have the exact resource but need to filter that on some optional traits such as color, size, etc.
GET /balloon/123?color=red&size=large

java.io.NotSerializableException: org.json.JSONObject

JDBCTemplate and MYSQL JSON
I am writing a rest service where i need to add few details at mysql table.
My mysql table as a column area_json as type json.
I got a pojo object from post call in rest service and i tried to insert it using jdbctemplate like
jdbcTemplate.update("insert into site(area_id,area_json) values(?,?)", area.getareaID(), area.getareaJson());
Once I do a post call using post man i get the below error
Invalid argument value: java.io.NotSerializableException;
nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException"
Please help
In the first place, be sure to use a version of Connector/J no older than v5.1.37, where support for the JSON datatype was added, and preferrably no older than v5.1.40, which fixed some JSON-related bugs. But if that's an issue for you, then it is at best secondary.
Before that even matters, JdbcTemplate needs to understand your JSONObject argument. The particular method you are using documents that the variable arguments, including your JSONObject are
arguments to bind to the query (leaving it to the PreparedStatement to
guess the corresponding SQL type); may also contain SqlParameterValue
objects which indicate not only the argument value but also the SQL
type and optionally the scale
When it says the PreparedStatement will guess, it can only mean the two-arg version of PreparedStatement.setObject() which documents:
The JDBC specification specifies a standard mapping from Java Object
types to SQL types. The given argument will be converted to the
corresponding SQL type before being sent to the database.
Note that this method may be used to pass datatabase- specific
abstract data types, by using a driver-specific Java type. If the
object is of a class implementing the interface SQLData, the JDBC
driver should call the method SQLData.writeSQL to write it to the SQL
data stream. If, on the other hand, the object is of a class
implementing Ref, Blob, Clob, NClob, Struct, java.net.URL, RowId,
SQLXML or Array, the driver should pass it to the database as a value
of the corresponding SQL type.
(Emphasis added.)
JDBC does not have built-in support for a JSON datatype. The docs do allow for Connector/J to provide a driver-specific type corresponding to the JSON SQL datatype, but just because MySQL and Connector/J support JSON does not mean you can pull a random JSON-representing object off the shelf and present it to them, nor indeed that they provide or accommodate a JSON-specific Java datatype at all. Inasmuch as MySQL seems not to publish or reference any documentation of JDBC extension APIs in its Connector/J developer guide, I'm inclined to doubt that it recognizes any such type.
It seems, then, that you should rely on the same technique that you would do when programming directly in MySQL's SQL dialect:
In MySQL, JSON values are written as strings. MySQL parses any string
used in a context that requires a JSON value, and produces an error if
it is not valid as JSON. These contexts include inserting a value into
a column that has the JSON data type and passing an argument to a
function that expects a JSON value [...].
(MySQL 5.7 Reference Manual, section 11.6)
That is, convert your JSONObject to a JSON-format String, and present it to your template that way. On retrieval, expect to have to do the reverse.

Encode/Decode a given Object with specific parameters

I have a class with 10s of parameters. I want to encode and decode (back to) this class with limited number of parameters (let's say 3). It means, I am not worried if other parameters change. Assume those keys to be primary keys of the table and we are only concerned about them.
I can obviously use Base64 encoding/decoding to do the final job but handing different object types among those parameters was coming out to be multiple lines of code (with type checks).
One better thing I can think of it using JSON parsing to convert objects first to a JSON then use the encoding but that will again need specifically choosing the parameters. What could be the best way to perform this?

Spring Data JPA Repository Queries - How to map #Param value to multiple parameter types

I have implemented following JPA Repository query for some common search functionality.
But with that query, due to age is a Integer value and mapping Parameter is String value I got some exception as follow. Is there any mechanism to implicitly casting parameter to relevant data type instead of we do that. Thanks.
Query with common parameter
#Query("select u from User u where u.firstname = :searchText or u.age = :searchText")
List<User> findBySearchText(#Param("searchText") String searchText);
Exception
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: integer = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
The issue you see has nothing to do with the binding itself. Spring Data basically binds the value you give to the named parameter searchText.
It looks like what happens next is that your persistence provider builds some SQL from it where there's a type mismatch apparently. Age doesn't seem to be of type String, is it? That said, I think trying to bind an arbitrary String to an integer (which it is I guess) is a very weird approach in the first place.
SQL is not really built to support arbitrary text search features and schema is helping you to detect invalid criterias (which it does in this case). Have you thought about adding a full-text search store (Elasticsearch, Solr or the like) and do the text searches in those?

Categories

Resources