Mapping json object to Spring object in REST service - json

I have a REST service defined in Spring as follows:
#RequestMapping(value = "/create", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<String> addArticle(#RequestBody Article article){
try{
articleService.addArticle(article.getTitle(),
article.getContent(),
article.getTags(),
article.getPublishStatus(),
article.getCompanyId(),
article.getCategory());
return new ResponseEntity<String>(HttpStatus.OK);
} catch (Exception e){
e.printStackTrace();
return new ResponseEntity<String>(e.getMessage(), HttpStatus.OK);
}
}
And my article is defined as follows:
public class Article {
private int id;
private String title;
private String content;
private String smsContent;
public String getSmsContent()
{
return smsContent;
}
public void setSmsContent(String smsContent)
{
this.smsContent = smsContent;
}
private String[] tags;
private int companyId;
private String category;
public String getCategory(){
return category;
}
public void setCategory(String category){
this.category = category;
}
private byte publishStatus;
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
public String getContent(){
return content;
}
public void setContent(String content){
this.content = content;
}
public String[] getTags(){
return tags;
}
public void setTags(String[] tags){
this.tags = tags;
}
public int getCompanyId(){
return companyId;
}
public void setCompanyId(int companyId){
this.companyId = companyId;
}
public byte getPublishStatus(){
return publishStatus;
}
public void setPublishStatus(byte publishStatus){
this.publishStatus = publishStatus;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
}
How do I call this service using Angular? I tried following code:
function createArticle(name, companyId, title, content, tags, category) {
var request = $http({
method : 'POST',
url : '/inbound/api/article/create.json',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
transformRequest : function(obj) {
var str = [];
for ( var p in obj)
str.push(encodeURIComponent(p) + "="
+ encodeURIComponent(obj[p]));
return str.join("&");
},
data : {
title : title,
content : content,
tags : tags,
companyId : companyId,
category: category
}
});
I am getting error 415 (Unsupported Media Type). Any ideas?

Since you're working with JSON, you need to set your form and handler accordingly.
REST handler
#RequestMapping(value = "/create", method = RequestMethod.POST, consumes = "application/json")
Angular
headers : {
'Content-Type' : 'application/json'
},

First
you have:
#RequestMapping(value = "/create", method = RequestMethod.POST)
just /create
Second
You have:
url : '/inbound/api/article/create.json',
Proceed to remove the .json that's the problem
Third
Be sure to indicate for the ajax event, the data you are sending is in JSON

Related

How can I read Blob in Spring Boot

I am beginner for Spring Boot and I save multiple files in my MySQL database which seems like below and it's working fine and now I want to retrieve saved files
I do not understand how can I read blob data and how to convert into a URL for showing users.
Controller
#RequestMapping(value = "/getUser", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
#ResponseBody
public DBFile getUserById(#RequestBody DBFile dBFile ) {
DBFile record = employeeRepository.findById(dBFile.getId());
return record;
}
Repository
public interface MultipartRepository1 extends JpaRepository<DBFile, Integer{}
DTO
#Entity
#Table(name = "files")
public class DBFile {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
private String file_name;
private String file_type;
#Lob
private byte[] data;
public DBFile() {
}
public DBFile(String file_name, String file_type, byte[] data) {
this.file_name = file_name;
this.file_type = file_type;
this.data = data;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFile_name() {
return file_name;
}
public void setFile_name(String file_name) {
this.file_name = file_name;
}
public String getFile_type() {
return file_type;
}
public void setFile_type(String file_type) {
this.file_type = file_type;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
Table
673e148e-a209-45c8-914c-7016dd59542f BLOB home_beach.jpg image/jpeg
a55777bc-5fda-41a7-a589-3731ae418262 BLOB beach-houses.jpg image/jpeg
ce3f502c-f780-4a7d-a7d1-e678adfa367d BLOB theahotel_logo.png image/png
Spring boot will automatically return your blob field as a base64 string e.g.
{"data": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAABfAAAAXwBsrqMZwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADdSURBVEiJtZTLCoUgEIZNaG90EfIFhXxTW6WbfJn/LA5xzOpUMg7MZmb4PvAyFWMMrGDwp4NSSqa1zpLgLqWU8N4DAIwxt/NJ/h9QSiGEAACw1kIIQSeI4fM8o2mat/BrQQxflgVd1+XAzwUpvO/7XPhRQAzfC2K4c44C/hOk8GEYKOBfQQz33lPCwdq2hXMOpYLXdc04f7wxsmK3CohezvGShRCw1gIA1nXFOI60goKSfaGA5Fgklpw3CCXXzVSilKIVpJIQQo7kfij+J9M00Qs2idb69RFVm6VUfACZhb1lipibXgAAAABJRU5ErkJggg=="}
You can return just that field from an endpoint. Then convert that to an image on the client application.

#RestController custom ResponseEntity - Jackson

What i'm trying to achieve here is to get a custom response from the RequestMapping, below is the structure of the json which I'm trying to get in case of an array of objects:
{
"error": false,
"message": "the message",
"data": [{},{},...]
}
and the below in case of object
{
"error": false,
"message": "the message",
"data": {}
}
The code is working fine but the problem is "data" will not always has an array, it may store an object, so what I tried is to create a custom POJO class which contains my custom response and when I want to annotate two attributes with same name i'm getting the below error
Could not find acceptable representation
And what if I create another class which will contain the same attributes but with an JsonObject not with array, is there any better way to achieve this ?
Below are my classes :
#JsonInclude(Include.NON_NULL)
public class JsonResponseObject<T> implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private boolean error;
private String message ;
#JsonProperty(value="data")
private ArrayList<T> array;
#JsonProperty(value="data")
private Object object ;
public JsonResponseObject() {
}
public boolean isError() {
return error;
}
public void setError(boolean error) {
this.error = error;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ArrayList<T> getArray() {
return array;
}
public void setArray(ArrayList<T> array) {
this.array = array;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
UserJsonController.java :
#RestController()
#RequestMapping(value = "/json")
public class UserJsonController {
#Autowired
private UserRepository userDAO;
#RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getUsers() {
ArrayList<Users> entityList = (ArrayList<Users>) userDAO.findAll();
JsonResponseObject<Users> jsonResponse = new JsonResponseObject<Users>();
jsonResponse.setError(false);
jsonResponse.setMessage("test");
jsonResponse.setArray(entityList);
return new ResponseEntity<>(jsonResponse, HttpStatus.OK);
}
#RequestMapping(value = "/users/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getUserByID(#PathVariable int id) {
JsonResponseObject<Users> jsonResponse = new JsonResponseObject<Users>();
jsonResponse.setError(false);
jsonResponse.setMessage("test");
jsonResponse.setObject(userDAO.findById(id).get());
return new ResponseEntity<>(jsonResponse, HttpStatus.OK);
}}

SpringBoot Rest response not deserialiazed with jackson

I am a running a project with SpringBoot. In this project I am calling an external Rest Service. I have modeled the response items into bean.
But when I get the response back the data are not serialised into the beans.
I guess there must be some configuration missing but I cannot find what.
I have added onfiguration spring-boot-starter-test to the configuration of Maven:
The rest client:
#RunWith(SpringRunner.class)
#SpringBootTest
public class RestClientTest {
#Autowired
private RestTemplateBuilder restTemplate;
#Test
public void sayHello() {
System.out.println("Hello");
assert(true);
}
#Test
public void testGetEmployee() {
RestTemplate template = restTemplate.build();;
HttpHeaders headers = new HttpHeaders();
List<MediaType> types = new ArrayList<MediaType>();
types.add(MediaType.APPLICATION_JSON);
types.add(MediaType.APPLICATION_XML);
headers.setAccept(types);
headers.set("Authorization", "Bearer gWRdGO7sUhAXHXBnjlBCtTP");
HttpEntity<Items> entity = new HttpEntity<Items>(headers);
String uri = "https://mytest.com/employees";
//ResponseEntity<String> rec = template.exchange(uri, HttpMethod.GET, entity, String.class);
//System.out.println("Received: " + rec);
ResponseEntity<Items> rec = template.exchange(uri, HttpMethod.GET, entity, Items.class);
System.out.println("Received: " + rec);
}
}
When I inspect the elements of the response it, I get a list, all the items are with null values
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public class Item implements Serializable {
#JsonProperty
private String id;
#JsonProperty
private String name;
#JsonProperty
private String email;
#JsonProperty
private String phone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public class Items implements Serializable {
#JsonProperty
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
return items;
}
}
Do you see what I am missing here?
The response is like this:
{
"items": [
{
"item": {
"id": 0,
"name": "string",
"email": "string",
"phone": "string",
Do you see what I am missing here?
Thanks
Gilles
The way you have implemented will try to deserialize data into Items class. But it doesn't have the required properties to deserialize. When you need to get a list of data through rest template exchange, you can get them as follows.
Get data as an array and convert it into arrayList.
Item[] itemArray = template.exchange(uri, HttpMethod.GET, entity, Item[].class).getBody();
List<Item> itemList = Arrays,asList(itemArray);
or
Use ParameterizedTypeReference to get data as a list
ResponseEntity<List<Item>> itemList = template.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<Item>>() {});
List<Item> itemList = template.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<Item>>() {}).getBody(); // access list directly
You might need to add this to your ObjectMapper:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
And on your entity add #JsonRootName("item")

Jackson JSON Can not construct instance of "About" : deserialize issue

I've make HttpsURLConnection to receive some information about my server.
The result of response is :
{"about":{"title":"NiFi","version":"1.1.0","uri":"https://localhost:443/api/","contentViewerUrl":"/nifi-content-viewer/","timezone":"CET"}}
How is possible to extract all attributes and key/value ?
About.class file
public class About {
private List<AboutObject> about;
public About()
{
// this.about = about;
}
public List<AboutObject> getAbout() {
return this.about;
}
public void setAbout(List<AboutObject> about) {
this.about = about;
}
}
AboutObject.class
public class AboutObject {
private String title;
private String uri;
private String contentViewerUrl;
private String timezone;
public String getTitle()
{
return this.title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getUri()
{
return this.uri;
}
public void setUri(String uri)
{
this.uri = uri;
}
public String getContentViewerUrl()
{
return this.contentViewerUrl;
}
public void setContentViewerUrl(String contentViewerUrl)
{
this.contentViewerUrl = contentViewerUrl;
}
public String getTimeZone()
{
return this.timezone;
}
public void setTimeZone(String timezone)
{
this.timezone = timezone;
}
}
Main.class
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
System.out.println("Contenu de in = " + in.toString());
ObjectMapper mapper = new ObjectMapper();
//Staff objStaff = new Staff();
System.out.println("Object to JSON in file");
mapper.writeValue(new File("output/file.json"), response);
System.out.println("Convert JSON string from file to Object");
//String about = mapper.readValue(new File("output/file.json"), String.class);
About about = mapper.readValue(new File("output/file.json"), About.class);
Error
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of About: no String-argument constructor/factory method to deserialize from String value ('{"about":{"title":"NiFi","version":"1.1.0","uri":"https://localhost:443/api/","contentViewerUrl":"/nifi-content-viewer/","timezone":"CET"}}') at [Source: output/file.json; line: 1, column: 1]
Thanks for you help
The test json you show doesn't have the array wrapper used in your About object. You're also missing the version field in your AboutObject and the timezone field uses the wrong case.
Your example worked when I updated your objects:
public class About {
private AboutObject about;
public AboutObject getAbout() {
return about;
}
public void setAbout(AboutObject about) {
this.about = about;
}
}
public class AboutObject {
private String title;
private String uri;
private String contentViewerUrl;
private String timezone;
private String version;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUri() {
return this.uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getContentViewerUrl() {
return this.contentViewerUrl;
}
public void setContentViewerUrl(String contentViewerUrl) {
this.contentViewerUrl = contentViewerUrl;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
Test:
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String obj = "{\"about\":{\"title\":\"NiFi\",\"version\":\"1.1.0\",\"uri\":\"https://localhost:443/api/\",\"contentViewerUrl\":\"/nifi-content-viewer/\",\"timezone\":\"CET\"}}";
About about = mapper.readValue(obj, About.class);
}

How to use native query with spring repo mapped to custom object?

I have table t1:
id | title
1 | title1
2 | title2
and I have the following spring repo method:
#Query(nativeQuery = true, value = "select id, title from t1")
public List<T1> getAll();
The custom class is:
public class T1 {
#JsonProperty("id")
private Integer id;
#JsonProperty("title")
private String title;
public T1(Integer id, String title) {
this.id = id;
this.title = title;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
I'm expecting to get the following json response:
{[{"id":1, "title":"titl1"}, {"id":2, "title":"titl2"}]}
However i'm getting this one:
[[1,"title1"],[2,"title2"]]
I'm using #RestController
#RequestMapping(method = RequestMethod.GET, value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntityTestResponse> test() {
List<T1> list = testRepository.getAll();
TestResponse response = new TestResponse(list);
return new ResponseEntity<TestResponse>(response, HttpStatus.OK);
}
TestResponse class is:
public class TestResponse implements Serializable {
private TreeSet<T1> list = new TreeSet<>();
public TestResponse(TreeSet<T1> list) {
this.list = list;
}
....
Can you help with that?
This response is classic Java List, if you need it as JSON object, you have to use for example GSON and then you should write something like this:
sonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
System.out.println(gson.toJson(YOUR_LIST_OF_T1));
Here are examples (included that was i wrote) and here is GitHub repo.
You can do it manually by overrite toString() method in T1 class if u need it in specific signature, and u didn't got any API doing what you want.
So if u try some thing like that
List<T1> list = testRepository.getAll();
StringBuilder strBuilder = new StringBuilder();
for(T1 t : list){
strBuilder.append(t.toString() + ", ");
}
String result = "";
if(strBuilder.length()!=0){
result = "{[" + strBuilder.substring(0, strBuilder.length()-2) + "]}";
}
System.out.println(result);
and class should overrite toString() method
class T1{
#JsonProperty("id")
private Integer id;
#JsonProperty("title")
private String title;
public T1(Integer id, String title) {
this.id = id;
this.title = title;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public String toString() {
return "{\"id:\"" + id + ", \"title:\"" + title + "}";
}
}
Also if you want to use pure java standard library you can do it like next code but you will need to download javax.json-xxxx.jar(for example >> javax.json-1.0.4.jar) (that include providers or the implementation) to your library project path
But this next code will generate something like that
[{"id":1,"title":"Title1"},{"id":2,"title":"Title2"},{"id":3,"title":"Title3"}]
List<T1> list = testRepository.getAll();
JsonArrayBuilder jsonArray = Json.createArrayBuilder();
for(T1 t : list) {
jsonArray.add(Json.createObjectBuilder()
.add("id", t.getId())
.add("title", t.getTitle()));
}
System.out.println(jsonArray.build());