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
Related
I am studying Spring Boot and I want to create a Rest Controller, and using a sql database, but there is a problem when I start the project :
Error:
(the error text is great I will leave the link)
And code:
OrderController.java
package ***;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
#RestController
public class OrderController {
#Autowired
private OrderRepository orderRep;
#GetMapping("/")
public List<Order> index(){
return (List<Order>) orderRep.findAll();
}
#GetMapping("/{id}")
public Order show(#PathVariable int id){
Optional<Order> orderId= orderRep.findById(id);
Order order = orderId.get();
return order;
}
#PostMapping("/search")
public List<Order> search(#RequestBody Map<String, String> body){
String searchItem = body.get("item");
return orderRep.findByTitleContainingOrContentContaining(searchItem);
}
#PostMapping("/")
public Order create(#RequestBody Map<String, String> body){
String item = body.get("item");
int price = Integer.parseInt(body.get("price"));
int quantity = Integer.parseInt(body.get("quantity"));
return orderRep.save(new Order(item, price,quantity));
}
#PutMapping("/{id}")
public Order update(#PathVariable String id, #RequestBody Map<String, String> body){
int orderId = Integer.parseInt(id);
// getting blog
Optional<Order> order = orderRep.findById(orderId);
order.get().setItem(body.get("item"));
order.get().setPrice(Integer.parseInt(body.get("price")));
order.get().setQuantity(Integer.parseInt("quantity"));
return orderRep.save(order.get());
}
#DeleteMapping("/{id}")
public boolean delete(#PathVariable int id){
//int orderId = Integer.parseInt(id);
orderRep.deleteById(id);
return true;
}
}
Order.java
package ***;
import javax.persistence.*;
#Entity
#Table(name = "orders")
public class Order {
//Fields
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "item")
private String item;
#Column(name = "price")
private int price;
#Column(name = "quantity")
private int quantity;
//Constructors
public Order() { }
public Order(String item, int price, int quantity) {
this.setItem(item);
this.setPrice(price);
this.setQuantity(quantity);
}
public Order(int id, String item, int price, int quantity) {
this.setId(id);
this.setItem(item);
this.setPrice(price);
this.setQuantity(quantity);
}
//Object to string data
#Override
public String toString() {
return "Order{" +
"id=" + getId() +
", item='" + getItem() + '\'' +
", price='" + getPrice() + '\'' +
", price='" + getQuantity() + '\'' +
'}';
}
//Getters & Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
OrderRepository.java
package ***;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface OrderRepository extends CrudRepository<Order, Integer> {
// custom query to search to blog post by title or content
List<Order> findByTitleContainingOrContentContaining(String item);
}
application.properties
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/testvoy?useUnicode=true&serverTimezone=UTC&useSSL=true&verifyServerCertificate=false
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
#spring.jpa.show-sql: true
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.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project</name>
<description>project</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-asciidoctor</artifactId>
<version>${spring-restdocs.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I would be grateful for any help, thanks in advance
If you check the error, you can see that it comes from there:
List<Order> findByTitleContainingOrContentContaining(String item);
and if you read more closely to the error, you will see:
No property title found for type Order!;
inside here:
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.List com.test.project.OrderRepository.findByTitleContainingOrContentContaining(java.lang.String)! Reason: Failed to create query for method public abstract java.util.List com.test.project.OrderRepository.findByTitleContainingOrContentContaining(java.lang.String)! No property title found for type Order!; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.test.project.OrderRepository.findByTitleContainingOrContentContaining(java.lang.String)! No property title found for type Order!
Infact, if you check your model, there is no title property
I have just begun to learn RESTful services and this is the issue I have been facing recently.
When I run the application to GET an XML type response, I get status code 500 and I don't see any stack trace for this as well. Am I missing anything in the dependency list ? Please help me figure this.
Here is the entity class :
import java.util.Date;
import jakarta.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Message {
private int id;
private String message;
private String author;
private Date date;
public Message() {}
public Message(int id, String message, String author) {
super();
this.id = id;
this.message = message;
this.author = author;
this.date = new Date();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Override
public String toString() {
return "Message [id=" + id + ", message=" + message + ", author=" + author + ", date=" + date + "]";
}
}
And then I have my service class : MessageService.java :
import java.util.ArrayList;
import java.util.List;
import org.aravind.restful.messenger.model.Message;
public class MessageService {
public List<Message> getMessages()
{
Message m1 = new Message(1,"Hello World!","aravind");
Message m2 = new Message(2,"First step towards the goal!","aravind");
List <Message> messageList = new ArrayList<Message>();
messageList.add(m1);
messageList.add(m2);
return messageList;
}
}
And then I have the resource class : MessengerResouce.java
package org.aravind.restful.messenger.resources;
import java.util.List;
import org.aravind.restful.messenger.model.Message;
import org.aravind.restful.messenger.service.MessageService;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
#Path("/messages")
public class MessengerResource {
#GET
#Produces(MediaType.APPLICATION_XML)
public List<Message> getMessages()
{
MessageService msgService = new MessageService();
return msgService.getMessages();
}
}
And here is how my pom.xml looks :
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.aravind.restful</groupId>
<artifactId>messenger</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>messenger</name>
<build>
<finalName>messenger</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<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>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<!-- uncomment this to get JSON support
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
-->
</dependencies>
<properties>
<jersey.version>3.0.0-M1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
Please help me figure this out. Thanks.
The link Sam suggested answers your question. You have to wrap your response as a GenericEntity. Here is the documentation from the Response class:
"It is the callers responsibility to wrap the actual entity with GenericEntity if preservation of its generic type is required."
So your code should look something like this:
#GET
#Produces(MediaType.APPLICATION_XML)
public Response getMessages()
{
MessageService msgService = new MessageService();
return Response.status(Status.OK)
.entity(new GenericEntity<>(msgService.getMessages(), List.class))
.build(); ;
}
Im making a Spring boot project and when running it says:
"Field trepository in com.example.trainerplanner.trainerController.TrainerController required a bean of type 'com.example.trainerplanner.model.domain.TrainerRepository' that could not be found."
I already cleaned the .m2 directory and tried to add/delete many different dependencies.
package com.example.trainerplanner;
#ComponentScan({"com.example.trainerplanner.model.domain"})
#EnableAutoConfiguration
#EnableJpaRepositories(basePackageClasses = {TrainerRepository.class, CategoryRepository.class})
#SpringBootApplication
public class TrainerplannerApplication {
private static final Logger log = LoggerFactory.getLogger(TrainerplannerApplication.class);
public static void main(String[] args) {
SpringApplication.run(TrainerplannerApplication.class, args);
}
#Bean
public CommandLineRunner trainerDemo(CategoryRepository crepository, TrainerRepository trepository) {
return (args) -> {
log.info("Save some exercises");
//Tässä kohdassa tehdään uudet kategoriat "c repositoryyn".
//Ensiksi on yläkropan päälihakset ja sitten alakropan
crepository.save(new Category("Biceps")); //Hauikset
crepository.save(new Category("Triceps")); //Ojentajat
crepository.save(new Category("Chest")); //Rinta
crepository.save(new Category("Shoulders")); //Olkapäät
crepository.save(new Category("Back")); //Selkä
crepository.save(new Category("Quadriceps")); //Etureidet
crepository.save(new Category("Hamstrings")); //Takareidet
crepository.save(new Category("Calves")); //Pohkeet
crepository.save(new Category("Glutes")); //Pakarat
trepository.save(new Trainer("Bicep curl", 8, 3, crepository.findByName("Biceps").get(0)));
trepository.save(new Trainer("Tricep extension", 8, 3, crepository.findByName("Triceps").get(0)));
trepository.save(new Trainer("Squat", 8, 3, crepository.findByName("Quadriceps").get(0)));
User userYksi = new User("user", "$2y$12$4iGWyQs5hC6ibe5Pq7ochekppUZcSfeIV.tjgZIuSobVA8B5vOhXK", "USER");
//Molemmat salasanat hashattu BCryptillä, roundit oli 12 ja 9
User userKaksi = new User("admin", "$2y$06$K9UJzObPGyroQKlkTzWWz.BlUurpYCMFelyvM/2AVYSbzogvd3.zq", "ADMIN");
urepository.save(userYksi);
urepository.save(userKaksi);
log.info("fetch all exercises");
for (Trainer trainer : trepository.findAll()) {
log.info(trainer.toString());
};
};}
This is the springbootapp
#Controller
#Component
#EnableJpaRepositories
public class TrainerController {
#Autowired
private TrainerRepository trepository;
#Autowired
private CategoryRepository crepository;
//Req. mappingeissä nähdään mikä menee urlin loppuun. esim. localhost:8080/trainerlist palauttaa trainerlist thymeleafsivun
//Metodit eri toiminnoille, esim lisää, poista, lista, tallenna.
#RequestMapping(value= {"/", "/trainerlist"})
public String trainerList(Model model) {
model.addAttribute("trainers", trepository.findAll());
return "trainerlist";
}
#RequestMapping(value = "/add")
public String addTrainer(Model model){
model.addAttribute("trainer", new Trainer());
model.addAttribute("category", crepository.findAll());
return "addtrainer";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(Trainer trainer){
trepository.save(trainer);
return "redirect:trainerlist";
}
//Poistaa ID:n avulla trainerin ja palauttaa //trainerlist-sivun
#RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public String deleteTrainer(#PathVariable("id") Long trainerId, Model model) {
trepository.deleteById(trainerId);
return "redirect:../trainerlist";
}
}
Controller class
#Repository
public interface CategoryRepository extends CrudRepository<Category, Long> {
List<Category> findByName(String name);
}
CategoryRepo, TrainerREpo is same but with different name.
#Component
public class TrainerModel {
public String Trainer(#RequestParam(value="name")String name, Integer reps, Integer sets, Model model) {
model.addAttribute("name", name);
model.addAttribute("reps", reps);
model.addAttribute("sets", sets);
return "index";
}
}
This is the TrainerModel class
#Component
#Entity
public class Trainer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String name;
private Integer reps, sets;
#ManyToOne
#JoinColumn(name = "categoryid")
#JsonManagedReference
private Category category;
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Trainer() {
//Tyhjä
}
public Trainer(String name, Integer reps, Integer sets, Category category) {
super();
this.name = name;
this.reps = reps;
this.sets = sets;
this.category =category;
}
//Asetetaan getterit ja setterit Traineriin.
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 Integer getReps() {
return reps;
}
public void setReps(Integer reps) {
this.reps = reps;
}
public Integer getSets() {
return sets;
}
public void setSets(Integer sets) {
this.sets = sets;
}
#Override
public String toString() { //Jos kategoria tyhjä niin palautetaan ensimmäinen kohta, muuten else-kohta.
if (this.category != null)
return "Trainer [id=" + id + ", name=" + name + ", reps=" + reps + ", =" + sets + " sets =" + this.getCategory() + "]";
else
return "Trainer [id=" + id + ", name=" + name + ", reps=" + reps + ", sets=" + sets + "]";
}
}
And This is the Trainer class
<?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.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>trainerplanner</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>trainerplanner</name>
<description>Trainer planner for exercising</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</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>
Pom xml, re did the whole project with spring initialzr but no effect.
EDIT: still currently getting this as an error:
2019-08-08 15:12:50.876 WARN 3164 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type '' not supported]
I'm not really sure why it's saying Content type ' ' not supported...
Also it works from postman but doesn't show xml, just shows json, even though I have selected application/xml for the header type
I'm trying to get my basic spring rest service to respond with XML. I've annotated all the elements and put headers that are supposed to accept XML. For some reason my client still gets the error "unsupported media type".
I tried putting #ResponseBody next to the methods in EmployeeService, but it ended up giving me a different error which was: [org.springframework.web.HttpMediaTypeNotSupportedException: Content type '' not supported]
Employee.java
public class Employee implements Serializable {
#XmlAttribute
private String id;
#XmlElement
private String name;
#XmlElement
private String description;
//private List<Team> teams;
public Employee() {
super();
}
public Employee(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
//this.teams = teams;
}
#XmlAttribute
public String getId() {
return id;
}
#XmlAttribute
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getName() {
return name;
}
#XmlElement
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getDescription() {
return description;
}
// public List<Team> getTeam() {
// return teams;
// }
#XmlElement
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return String.format(
"employee [id=%s, name=%s, description=%s]", id,
name, description);
}
}
EmployeeController.java
#RestController
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping(path = "/employees", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public #ResponseBody HashMap<String, Employee> retrieveEmployees() {
return employeeService.retrieveAllEmployees();
}
#GetMapping(path = "/employees/{employeeId}",produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public #ResponseBody Employee retrievebyId(#PathVariable String employeeId) {
return employeeService.retrieveEmployee(employeeId);
}
#PostMapping(path="/employees")
public ResponseEntity<Void> registeremployee(#RequestBody Employee newemployee) {
Employee employee = employeeService.addEmployee(newemployee.getId(),newemployee.getName(), newemployee.getDescription());
if (employee == null)
return ResponseEntity.noContent().build();
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(
"/{id}").buildAndExpand(employee.getId()).toUri();
return ResponseEntity.created(location).build();
}
}
EmployeeService.java
#Component
public class EmployeeService {
static HashMap<String, Employee> employees = new HashMap<>();
static {
//Initialize Data
Team team1 = new Team("t1", "Java team", "Java Dev Team");
Employee Joe = new Employee("employee1", "Joe Smith","Human Resources");
Employee Bob = new Employee("employee2", "Bob Jones",
"Developer");
employees.put("employee1", Joe);
employees.put("employee2", Bob);
}
public HashMap<String, Employee> retrieveAllEmployees() {
return employees;
}
public Employee retrieveEmployee(String employeeId) {
return employees.get(employeeId);
}
//private SecureRandom random = new SecureRandom();
public Employee addEmployee(String id, String name, String description) {
//String randomId = new BigInteger(130, random).toString(32);
Employee employee = new Employee(id, name, description);
employees.put(id, employee);
return employee;
}
}
RestClient.java
public class RestClient {
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = restTemplate.headForHeaders(uri);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
public static void postJsonEmployee(String id, String name, String description) {
final String uri = "http://localhost:8080/employees/";
Employee newemp = new Employee(id, name, description);
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = restTemplate.headForHeaders(uri);
httpHeaders.setContentType(MediaType.APPLICATION_XML);
Employee result = restTemplate.postForObject( uri, newemp, Employee.class);
httpHeaders.setContentType(MediaType.APPLICATION_XML);
}
public static void main(String[] args) throws IOException, JSONException {
System.out.println("GET or POST?");
BufferedReader getpost = new BufferedReader(new InputStreamReader(System.in));
String selection = getpost.readLine();
switch(selection) {
case "GET":
System.out.println("Type in the employee's ID");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String employeeid = reader.readLine();
getJsonEmployee(employeeid);
break;
case "POST":
System.out.println("Type in the employee's ID");
Scanner scan = new Scanner(System.in);
String newid = scan.nextLine();
System.out.println("Type in the employee's name");
String newname = scan.nextLine();
System.out.println("Type in the employee's description");
String newdesc = scan.nextLine();
postJsonEmployee(newid, newname, newdesc);
break;
}
}
}
10:00:37.986 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP HEAD http://localhost:8080/employees/
10:00:38.293 [main] DEBUG org.springframework.web.client.RestTemplate - Response 415 UNSUPPORTED_MEDIA_TYPE
Exception in thread "main"
org.springframework.web.client.HttpClientErrorException$UnsupportedMediaType: 415 null
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:95)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.headForHeaders(RestTemplate.java:362)
at com.client.clientmodel.RestClient.getJsonEmployee(RestClient.java:52)
at com.client.clientmodel.RestClient.main(RestClient.java:104)
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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>employee-model</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>employee-model</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The 405 indicates your client is sending a bad request. You are issuing an HTTP HEAD request in your client. Try just "newing" HttpHeaders.
Also can't set headers on a request after sending the request.
Http status code series 4xx means a client-side problem. 415 means Unsupported media type.
I am not a java guy but I faced exactly this issue before at ajax call.
To solve this issue I add a headder which is Accept: "*/*" this solution is for ajax request. For java, I believe it will be
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = restTemplate.headForHeaders(uri);
headers.add("Accept", "*/*");
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
Can you try with the following code. I have modified only getJsonEmployee() method.
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity entity = new HttpEntity(headers)
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
String result = response.getBody();
System.out.println(result);
}
Besides, I see that your Employee class to generate XML is not right, I provide below the proposed Employee class and there is a main method also so that you can run to test the generation of XML structure.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
#XmlRootElement
public class Employee implements Serializable {
private String id;
private String name;
private String description;
// private List<Team> teams;
public Employee() {
super();
}
public Employee(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
// this.teams = teams;
}
#XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return String.format("employee [id=%s, name=%s, description=%s]", id, name, description);
}
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Employee emp = new Employee("id1", "name-1", "desc-1");
marshaller.marshal(emp, System.out);
}
}
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.