JSON format of result isn't correct - java

I have developed RESTful web service which is running fine I have used one POJO and one service class that is shown below but the issue is that in the output it is showing extra $ please advise how to correct that right now the output is coming as
{
"student":{
"#id":"10",
"age":{
"$":"25"
},
"collegeName":{
"$":"UP College"
},
"name":{
"$":"Ram"
}
}
}
and I want that output should be
{
"student":{
"#id":"10",
"age":25,
"collegeName":"UP College",
"name":"Ram"
}
}
so below is my POJO
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "student")
public class Student {
private int id;
private String name;
private String collegeName;
private int age;
#XmlAttribute
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
public int getAge() {
return age;
}
#XmlElement
public void setAge(int age) {
this.age = age;
}
}
below is my service class
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.jboss.resteasy.annotations.providers.jaxb.json.BadgerFish;
#Path("/restwb")
public class StudentService {
#BadgerFish
#GET
//#Path("/{id}")
#Produces("application/json")
public Student getStudentDetails(){
Student student = new Student();
student.setId(10);
student.setName("Ram");
student.setCollegeName("UP College");
student.setAge(25);
return student;
}
}
and here is my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.concretepage</groupId>
<artifactId>RestWB</artifactId>
<version>1</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jettison-provider</artifactId>
<version>3.0.4.Final</version>
</dependency>
</dependencies>
</project>

Yes, this is the documented behaviour of Badgerfish:
Text content of elements goes in the $ property of an object.
From the documentation, there's no obvious way of transforming to object properties that don't have an #. (If you're happy with #age, you could use an XmlAttribute for age instead of XmlElement.)
But as you don't seem to have any need for an XML representation anyway, I'd suggest moving away from Badgerfish for your JSON representation, as Badgerfish is explicitly meant to be a transform from XML documents to JSON documents.

The format you get is what Badgerfish you gives. There is no way to change it. Either remove Badgerfish at all and get convenient JSON, or consume the result of this library's work.

Related

MOXy XPath unmarshalling Element is null

Im trying to unmarshall the camunda:property elements into a List using XPath to skip the unnecessary wrapper elements. Unfortunately my propertyList is always null. This is located in the Task Class. Any help would be greatly appreciated.
Edit#1:
I followed the following links who were supposed to help with my problem unfortunately without success. http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html which is the official guide. Apparently there are some challenges with the maven pom.xml file. I suspect that the problem lies inside the pom file.
I followed this guide https://www.javacodegeeks.com/2012/07/eclipselink-moxy-as-jaxb-provider.html but still did not get it to work.
pom.xml file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>BPMN-Marshaller</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<repositories><repository>
<id>EclipseLink Repo</id>
<url>http://download.eclipse.org/rt/eclipselink/maven.repo</url>
<name>EclipseLink Repo</name>
</repository></repositories>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>3.0.0-M1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<!-- Runtime, com.sun.xml.bind module -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
</project>
jaxb.properties file in the same package and folder as my java classes(see attached image with name "Project Structure")
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
package-info.java file
#XmlSchema(namespace="http://www.omg.org/spec/BPMN/20100524/MODEL", elementFormDefault=XmlNsForm.QUALIFIED, xmlns = {#XmlNs(prefix="bpmn", namespaceURI="http://www.omg.org/spec/BPMN/20100524/MODEL")
,#XmlNs(prefix = "camunda", namespaceURI = "http://camunda.org/schema/1.0/bpmn")})
package bpmn;
import javax.xml.bind.annotation.*;
xml file snippet
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_13d3a6z" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.1.1">
<bpmn:process id="Process_1tovjba" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_06i118e</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Activity_1d3friu" name="Task 1">
<bpmn:extensionElements>
<camunda:properties>
<camunda:property name="start_date" value="01-04-2018" />
<camunda:property name="duration" value="5" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_06i118e</bpmn:incoming>
<bpmn:outgoing>Flow_0linmbs</bpmn:outgoing>
</bpmn:task>
Definitions Class
#XmlRootElement
public class Definitions {
private String id;
private Process process;
public Definitions(){};
public Definitions(String id, Process process){
super();
this.id = id;
this.process = process;
}
#XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement
public Process getProcess() {
return process;
}
public void setProcess(Process process) {
this.process = process;
}
#Override
public String toString(){
return "Definitions [id23=" + id + ", process=23499999999999999" + process + "]";
}
}
Process Class
public class Process {
private String id;
private List<Task> taskList;
private List<SequenceFlow> sequenceFlowList;
public Process(){};
public Process(String id, List<Task> taskList, List<SequenceFlow> sequenceFlowList){
super();
this.id = id;
this.taskList = taskList;
this.sequenceFlowList = sequenceFlowList;
}
#XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "task")
public List<Task> getTaskList() {
return taskList;
}
public void setTaskList(List<Task> taskList) {
this.taskList = taskList;
}
#XmlElement(name = "sequenceFlow")
public List<SequenceFlow> getSequenceFlowList() {
return sequenceFlowList;
}
public void setSequenceFlowList(List<SequenceFlow> sequenceFlowList) {
this.sequenceFlowList = sequenceFlowList;
}
}
Task Class
public class Task {
private String id;
private String name;
private List<Property> propertyList;
public Task(){}
public Task(String id, String name, List<Property> propertyList){
super();
this.id = id;
this.name = name;
this.propertyList = propertyList;
}
#XmlAttribute
#JsonProperty("text")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "property")
#XmlPath("bpmn:extensionElements/camunda:properties/camunda:property")
public List<Property> getPropertyList() {
return propertyList;
}
public void setPropertyList(List<Property> propertyList) {
this.propertyList = propertyList;
}
}
Property Class
public class Property {
private String name;
private String value;
public Property(){}
public Property(String name, String value) {
super();
this.name = name;
this.value = value;
}
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlAttribute
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Main Class
public class XMLToObject {
public static void main(String[] args) {
try {
File file = new File("process.bpmn");
JAXBContext jaxbContext = JAXBContext.newInstance(Definitions.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Definitions definitions = (Definitions) jaxbUnmarshaller.unmarshal(file);
System.out.println(definitions.getProcess().getTaskList().get(0).getPropertyList());
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Project Structure
I made the following changes to your approach, and I am able to access the duration and start_date properties data from your XML file.
I am using OpenJDK 14, by the way. But this approach runs OK using version 8 also.
The POM I am using has the following dependencies:
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<!--
Use 2.3.1 below to prevent "illegal
reflective access operation" warnings.
-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.7.6</version>
</dependency>
(I skipped the Jackson dependency just for this test.)
I also added the following section at the end of my POM, to handle the properties file:
<!-- to copy the jaxb.properties file to its class package: -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build>
This ensures the properties file is deployed to the correct location with its related class files.
I added the code to check for which JAXB provider is being used - just as a positive confirmation:
private void checkProvider() throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(Definitions.class);
String jaxbContextImpl = jc.getClass().getName();
if(MOXY_JAXB_CONTEXT.equals(jaxbContextImpl)) {
System.out.println("EclipseLink MOXy");
} else if(METRO_JAXB_CONTEXT.equals(jaxbContextImpl)) {
System.out.println("Metro");
} else {
System.out.println("Other");
}
}
I modified the code to loop through the properties data, to explicitly print the final properties values:
List<Property> props = definitions.getProcess().getTaskList().get(0).getPropertyList();
props.forEach(prop -> {
System.out.println(prop.getName() + " - " + prop.getValue());
});
//System.out.println(definitions.getProcess().getTaskList().get(0).getPropertyList());
The resulting output is:
EclipseLink MOXy
start_date - 01-04-2018
duration - 5

Using customized ObjectWriter with Jersey

I am developing a REST webservice. Jersey as jax-rs provider and Jackson for serialization/deserialization. I also develop the client based on Retrofit2.
My class hierarchy is provided by a third-party library and all classes descend from a root base class BaseObject. Some of those classes have undesirable getters, e.g. isEmpty, that I want to ignore on serialization (Note that it is important that they do not get serialized at all and using FAIL_ON_UNKNOWN_PROPERTIES on deserialization is not enough in my case).
I have used Jackson #JsonFilter on BaseClass using Mixins. To apply a filter, as far as I know, one has to use the following:
new ObjectMapper().writer(filterProvider).writeValueAsString...
Everything is ok up to here: the undesired property is successfully filtered from the produced json.
Now I have to configure Jersey and Retrofit2 to use my customized json serializer/deserializer.
For Jersey, serialization/deserialization can be configured using a Provider class that implements ContextResolver<ObjectMapper> and returning customized ObjectMapper in getContext(Class<?> type) method.
Similarly in Retrofit2, by using
Retrofit.Builder().addConverterFactory(JacksonConverterFactory.create(objectMapper)), one can customize serialization/deserialization.
THE PROBLEM IS THAT new ObjectMapper().writer(filterProvider) is of type ObjectWriter and not of type ObjectMapper. How can I tell Jersey and Retrofit2 to use my customized ObjectWriter which uses my filters?
Since version 2.6 of Jackson it has the 'setFilterProvider' method for an ObjectMapper.
I didn't try it but the documentation has the description for this: https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/ObjectMapper.html#setFilterProvider-com.fasterxml.jackson.databind.ser.FilterProvider-. You can try i think because the description fits for your case.
I built a test service with Jersey 2.7 and Jackson 2.9.5. it works fine but you have to know some tricks to run it.
In pom.xml add Jersey and Jackson:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.7</jersey.version>
<jackson.version>2.9.5</jackson.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
You have to define this dependence:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
it's mandatory.
In web.xml you have to make the ref to configuration of your service:
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>org.glassfish.jersey.server.ResourceConfig</param-name>
<param-value>com.home.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
MyApplication.java:
package com.home;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;
#ApplicationPath("/webapi")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(ObjectMapperProvider.class);
register(JacksonFeature.class);
register(MyResource.class);
}
}
With a custom ObjectMapperProvider you have to register a JacksonFeature.class because without it Jersey doesn't use the custom ObjectMapperProvider.
ObjectMapperProvider.java:
package com.home;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
#Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>{
final ObjectMapper defaultObjectMapper;
public ObjectMapperProvider() {
defaultObjectMapper = createDefaultMapper();
}
#Override
public ObjectMapper getContext(Class<?> type) {return defaultObjectMapper;}
public static ObjectMapper createDefaultMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setFilters(new SimpleFilterProvider().addFilter("dataFilter", SimpleBeanPropertyFilter.serializeAllExcept("region", "city")));
return mapper;
}
}
To define a filter use the 'setFilters' methods. This method is deprecated but the Jersey's library which called 'jersey-hk2' doesn't know the new method 'setFilterProvider' and throws an exception. With the old method everything works fine.
A business object with #JsonFilter:
#JsonFilter("dataFilter")
public class SimpleData {
#JsonProperty("name")
String firstName;
#JsonProperty("secondName")
String lastName;
#JsonProperty("country")
String country;
#JsonProperty("region")
String region;
#JsonProperty("city")
String city;
#JsonProperty("genre")
String genre;
public SimpleData() {
this.firstName = "Bryan";
this.lastName = "Adams";
this.country = "Canada";
this.region = "Ontario";
this.city = "Kingston";
this.genre = "Rock";
}
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getCountry() { return country; }
public void setCountry(String country) { this.country = country; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getGenre() { return genre; }
public void setGenre(String genre) { this.genre = genre; }
}
MyResource.java:
#Path("myresource")
public class MyResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public SimpleData getIt() {
return new SimpleData();
}
}
A filtered result:

Springboot doesn't work except when hello is typed

I created a very simply SpringBoot project using my groupId and artifactId. Looks like it doesn't want to kick off and some mappings are missing. But when I use the same package names and classnames as the SPring Boot tutorial which is on spring.io site, it works.
My POM is the following:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.spring</groupId>
<artifactId>firstspringboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<url>http://maven.apache.org</url>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
My Resource 'Greeting'
package com.my.spring.firstspringboot.entities;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class Greeting {
private String id;
private String firstName;
private String lastName;
public Greeting() {
}
public Greeting(String firstName, String lastName) throws NoSuchAlgorithmException {
this.setFirstName(firstName);
this.setLastName(lastName);
this.setId(new StringBuilder().append(SecureRandom.getInstance("SHA1PRNG").nextInt()).append("_").append(System.currentTimeMillis()).toString());
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return new StringBuilder().append("{\n\"name\":\"").append(this.firstName).append(" ").append(this.lastName).append("\"\n").append(",").append("{\n\"id\":\"").append(this.id).append("\"").toString();
}
}
And its Controller:
package com.my.spring.firstspringboot.controllers;
import java.security.NoSuchAlgorithmException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.my.spring.firstspringboot.entities.Greeting;
#RestController
public class GreetingController {
#RequestMapping("/")
public String home() {
return "Welcome!";
}
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(name="name",defaultValue="John") String name) throws NoSuchAlgorithmException {
return new Greeting(name,name);
}
}
And main App
package com.my.spring.firstspringboot.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class App
{
public static void main(String[] args)
{
SpringApplication.run(App.class, args);
}
}
Is there something more that I need to do here? I thought it's simply a boot and autoconfigure by default.
Try to add http method in your requestMapping
#RequestMapping(path = "/hello", method=RequestMethod.GET)
or try removing first endpoint which you have declared with path "/"
According to the documentation (Thanks to #JBNizet for pointing that out), I needed to keep my main application under the package name com.my.spring.firstspringboot
The reason is that Spring looks immediately under the firstspringboot subpackage to find the execution class since it's the artifact ID.
The correct approach should probably be the following:
1) Keep the app runner class in higher subpackage than resource/controller classes.
e.g com.my.firstapplication.App, com.my.firstapplication.resources.Resource etc.
2) If I rely on manual settings, use #EnableAutoConfiguration and #ComponentScan
3) If I am relying on Spring to do it - it's #SpringBootApplication

How to get a XML respose for a api which returns a response entity consisting of a list of object

I have written a REST API in spring boot. The API returns a list of object as a response. I am returning a ResponseEntity object from the API's controller class. But the XML output I get is not properly formatted. I am using com.fasterxml.jackson.dataformat library.
The POM file for the Project is:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>sampleapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My controller class is:
TestController.java
package com.example.sampleapi.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.sampleapi.Entity.Student;
import com.example.sampleapi.Entity.StudentResponse;
import com.example.sampleapi.dao.StudentDAO;
#RestController
public class TestController {
#Autowired
private StudentDAO studentDao;
#RequestMapping(value = "/save", method =RequestMethod.GET,
produces = {
MediaType.APPLICATION_XML_VALUE})
public boolean saveAllStudents() {
return studentDao.saveStudents();
}
#RequestMapping(value = "/get", method =RequestMethod.GET, produces = {
MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<StudentResponse> getAllStudents() {
List<Student> studentList = studentDao.getAllStudent();
int count = studentList.size();
StudentResponse studentResponse = new StudentResponse();
studentResponse.setStudentList(studentList);
studentResponse.setCount(count);
return new ResponseEntity<StudentResponse>(studentResponse, HttpStatus.OK);
}
}
My DAO class is:
StudentDAOImpl.java
package com.example.sampleapi.dao.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.example.sampleapi.Entity.Student;
import com.example.sampleapi.dao.StudentDAO;
#Repository
public class StudentDAOImpl implements StudentDAO {
private List<Student> studentDetails = new ArrayList<>();
#Override
public boolean saveStudents() {
Student student1 = new Student();
student1.setName("A");
student1.setAge(23);
student1.setMarks(100);
Student student2 = new Student();
student2.setName("B");
student2.setAge(25);
student2.setMarks(90);
Student student3 = new Student();
student3.setName("C");
student3.setAge(19);
student3.setMarks(95);
studentDetails.add(student1);
studentDetails.add(student2);
studentDetails.add(student3);
if(studentDetails.size() > 0) {
return true;
} else {
return false;
}
}
#Override
public List<Student> getAllStudent() {
return studentDetails;
}
}
The Student Entity class is as follows:
Student.java
package com.example.sampleapi.Entity;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Student {
private String name;
private int age;
private double marks;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getMarks() {
return marks;
}
public void setMarks(double marks) {
this.marks = marks;
}
#Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", marks=" + marks + "]";
}
}
The Response class is as follows:
StudentResponse.java
package com.example.sampleapi.Entity;
import java.util.List;
public class StudentResponse {
int count;
List<Student> studentList;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
The Xml response for the /get RequestMapping is :
<StudentResponse>
<count>3</count>
<studentList>
<studentList>
<name>A</name>
<age>23</age>
<marks>100.0</marks>
</studentList>
<studentList>
<name>B</name>
<age>25</age>
<marks>90.0</marks>
</studentList>
<studentList>
<name>C</name>
<age>19</age>
<marks>95.0</marks>
</studentList>
</studentList>
</StudentResponse>
Why the Student objects inside the list are coming as <studentList></studentList>, it should be <student></student> instead?
The XML format I am expecting is:
<StudentResponse>
<count>3</count>
<studentList>
<student>
<name>A</name>
<age>23</age>
<marks>100.0</marks>
</student>
<student>
<name>B</name>
<age>25</age>
<marks>90.0</marks>
</student>
<student>
<name>C</name>
<age>19</age>
<marks>95.0</marks>
</student>
</studentList>
</StudentResponse>
The reason you get the outer studentList is that that is the property name of that list in the StudentResponse.
The reason you get the inner studentList is that
When a collection property is annotated just with #XmlElement [as is assumed in Spring Boot when you don't have any annotation], each item in the collection will be wrapped by an element.
Source
You'll need to put annotations on your Java classes to get the result you want, in this case something like shown here
public class Customer {
#XmlElementWrapper(name="studentList")
#XmlElement(name="student")
private List<Student> studentList;
}
Try this out
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "student")
public class Student {
...
}

spring boot data jpa mysql could not create database

I am new in spring
I will post my code,
that the application.properties
spring.datasource.url=jdbc:mysql://localhost/spring
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
and this my entity
package model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String phone;
private String adresse;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
public Person(long id, String name, String phone, String adresse) {
super();
this.id = id;
this.name = name;
this.phone = phone;
this.adresse = adresse;
}
public Person() {
super();
}
}
and this is the repository
package repositry;
import org.springframework.data.jpa.repository.JpaRepository;
import model.Person;
public interface PersonRespositry extends JpaRepository<Person, Long> {
}
and my controller
package contoller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import model.Person;
import repositry.PersonRespositry;
#RestController
public class PersonController {
PersonRespositry rp;
#Autowired
public PersonController(PersonRespositry rp) {
// TODO Auto-generated constructor stub
this.rp=rp;
}
#RequestMapping("/find")
public Person find(long id){
return rp.findOne(id);
}
#RequestMapping("/findall")
public List<Person> findall(){
return rp.findAll();
}
#RequestMapping(value="/hello")
public String Demo(){
return "Hello world !!";
}
#RequestMapping(value="/create", method=RequestMethod.GET)
public String create(){
Person p=new Person();
p.setName("med");
p.setPhone("233888");
p.setAdresse("rue ");
rp.save(p);
return " success";
}
}
This is the architect of the project:
When I run the application the database does not generate and only the
localhost:8080 is running.
Your problem is the location of the Application.java.
#ComponentScanlooks for Spring beans inside the package of the class annotated with (#SpringBootApplication contains #ComponentScan) and in subpackages of this package.
I already provided an example to a very similar setup.
Please have a look here: https://stackoverflow.com/a/27983870/2576531
Furthermore the hint of Robert Moskal is correct. The database itself has to exist already. Only the tables will be created automatically.
If you want the data to be created you need to use create or create-drop. If you are using something like mysql you'll need to have created at least the database. The tables will be created for you.
I be very careful about doing this against a production database instance.
Otherwise for me it dosen't work with #componentScan but it works now with #EntityScan(basePackages = { "com.jwt.entites" }) in the main class to scan entity classes ..
This is not the answer but this is a sample. I think this will help you
//Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wisdom.spring.myjdbc</groupId>
<artifactId>spring_boot_jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring_boot_jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
//application Config
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/wisdom
spring.datasource.username=root
spring.datasource.password=8855
spring.jpa.generate-ddl=true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
server.port = 8585
package com.wisdom.spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wisdom.spring.model.students;
import com.wisdom.spring.repo.students_repo;
#RestController
#RequestMapping("/students")
public class studentController {
#Autowired
students_repo STDRepo;
#GetMapping(value = "/a")
public String a() {
return "hello";
}
#GetMapping(value = "/save")
public List<students> getStudents(){
System.out.println("Data returned");
return STDRepo.findAll();
}
#PostMapping(value = "/savestd")
public void saveBurger(students student) {
STDRepo.save(student);
}
}
package com.wisdom.spring.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class students {
#Id
#Column
private int s_id;
#Column
private String name;
#Column
private String address;
public students() {
}
public students(int s_id, String name, String address) {
this.s_id = s_id;
this.name = name;
this.address = address;
}
public int getS_id() {
return s_id;
}
public void setS_id(int s_id) {
this.s_id = s_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package com.wisdom.spring.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import com.wisdom.spring.model.students;
public interface students_repo extends JpaRepository<students,String> {
}
package com.wisdom.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
}

Categories

Resources