Goal: Marshalling and unmarshalling the clinic.xml correctly
Problem: Reading out the id's of the physiotherapist (people who work in the clinic)
This is the clinic.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<clinic clinicNumber="1">
<name>ClinicStackOverFlow</name>
<address>Deadbrains</address>
<zipCode>SomeZip</zipCode>
<city>City</city>
<phoneNumber>069441341341</phoneNumber>
<!-- LIST OF THE ID's of physiotherapists that work here -->
<physiotherapists>1</physiotherapists>
<physiotherapists>2</physiotherapists>
</clinic>
Clinic.java
package fysio.shared.domain;
import com.sun.deploy.xml.XMLable;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Clinic {
/**
* The identifier of a clinic
*/
#XmlID
#XmlAttribute
#XmlJavaTypeAdapter(IDStringAdapter.class)
private String clinicNumber;
/**
* The name of a clinic
*/
private String name;
/**
* The address where the clinic is located
*/
private String address;
/**
* The zip code of a clinic
*/
private String zipCode;
/**
* The city a clinic is located in
*/
private String city;
/**
* The phone number of a clinic
*/
private String phoneNumber;
#XmlIDREF
private List<Physiotherapist> physiotherapists;
/**
* The default constructor for Jaxb
*/
public Clinic() {
}
public Clinic(String clinicNumber, String name, String address, String zipCode, String city, String phoneNumber, List<Physiotherapist> physiotherapists) {
this.clinicNumber = clinicNumber;
this.name = name;
this.address = address;
this.zipCode = zipCode;
this.city = city;
this.phoneNumber = phoneNumber;
this.physiotherapists = physiotherapists;
}
/**
* Returns the number of a clinic
*
* #return The number of a clinic
*/
public String getClinicNumber() {
return clinicNumber;
}
/**
* Sets the number of a clinic
*
* #param clinicNumber the number of a clinic
*/
public void setClinicNumber(String clinicNumber) {
this.clinicNumber = clinicNumber;
}
public List<Physiotherapist> getPhysiotherapists() {
return physiotherapists;
}
/**
* Sets the physiotherapists of a clinic
*
* #param physiotherapists The Physiotherapists of a clinic
*/
public void setPhysiotherapists(List<Physiotherapist> physiotherapists) {
this.physiotherapists = physiotherapists;
}
/**
* adds a physiotherapist to a clinic
*
* #param physiotherapist The physiotherapist that needs to be added to a clinic
*/
public void addPhysiotherapist(Physiotherapist physiotherapist) {
physiotherapists.add(physiotherapist);
}
}
We have a list of physiotherapists (in xml)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<physiotherapists>
<physiotherapist physiotherapistNumber="1">
<clinic>1</clinic>
<name>Henk</name>
</physiotherapist>
<physiotherapist physiotherapistNumber="2">
<clinic>8</clinic>
<name>Klaas</name>
</physiotherapist>
</physiotherapists>
Physiotherapist.java (singular)
package fysio.shared.domain;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Physiotherapist {
#XmlAttribute
#XmlID
private String physiotherapistNumber;
#XmlIDREF
private Clinic clinic;
private String name;
public Physiotherapist() {
//Default empty constructor for JAXB
}
public Physiotherapist(String name, Clinic clinic) {
this.clinic = clinic;
this.name = name;
}
public Clinic getClinic() {
return clinic;
}
public String getPhysiotherapistNumber() {
return physiotherapistNumber;
}
public void setPhysiotherapistNumber(String physiotherapistNumber) {
this.physiotherapistNumber = physiotherapistNumber;
{}
}
Physiotherapists.java (plural)
#XmlRootElement(name = "physiotherapists")
#XmlAccessorType(XmlAccessType.FIELD)
public class Physiotherapists {
#XmlElement(name = "physiotherapist")
private List<Physiotherapist> physiotherapistList;
public Physiotherapists() {
//empty constructor for xml parsing
physiotherapistList = new ArrayList<Physiotherapist>();
}
public List<Physiotherapist> getPhysiotherapistList() {
return physiotherapistList;
}
}
And finally the unmarshalling part:
try {
JAXBContext jc = JAXBContext.newInstance(Clinic.class, Physiotherapist.class, Physiotherapists.class);
File clinicXML = new File("src/test/resources/data/xml/clinic.data");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Clinic clinicXMLData = (Clinic) unmarshaller.unmarshal(clinicXML);
File fysiotherapistXML = new File("src/test/resources/data/xml/physiotherapist.data");
Unmarshaller unmarshaller2 = jc.createUnmarshaller();
Physiotherapists ph = (Physiotherapists) unmarshaller2.unmarshal(fysiotherapistXML);
} catch (JAXBException e) {
e.printStackTrace();
}
Both unmarshallers do the best they can. I get a nice list of physiotherapist from unmarshaller 2 but I don't get anything about the physiotherapists from the clinic unmarshaller:
http://imgur.com/Mpcgm8t (stack didn't let me upload pics)
I kinda lost it... not knowing anymore whats wrong and correct. Tried many solutions online, understand the most of them but still missing something.
(It's a school project and it's not yet refactored)
How should it be possible to get the physiotherapists (PT) references into the Clinic objects when unmarshalling the PT list has no connection whatsoever to those Clinic objects? The Clinics have been built from the XML data, and there are no PTs in it, period.
For XmlID and XmlIDREF to work, i.e., to store an object reference in the field annotated XmlIDREF there must be an object of suitable type and with the matching value in its XmlID field within the same XML file.
You must combine the XML data into a single file.
Seeing that you reference the Clinic from the PT and the PTs from the Clinic, I'm afraid that you'll encounter difficulties in one direction even then. (I might be wrong - it's too long since I tried this.)
Now I think that you may not want to merge the XML files anyway. To solve your predicament, I suggest that you drop the ID and IDREF annotations and set the links "by hand". A single pass through the PT list is sufficient, a simple and robust solution.
Related
I have an abstract class named Staff. Instructor and Lecturer are the derived classes from the Staff superclasses. I need to use hibernate annotations into the Instructor and Lecturer classes.
Staff.java
public abstract class Staff {
private int staffID;
private String firstName;
private String lastName;
private String mobile;
private String email;
private double salary;
private String city;
private String street;
//getters and setters
}
This is the subclass and I used staffID again in the subclass to apply the #Id annotation.
Lecturer.java
#Entity
#Table(name = "lecturer")
public class Lecturer extends Staff {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int staffID;
private int lectureHours;
public int getLectureHours() {
return lectureHours;
}
public void setLectureHours(int lectureHours) {
this.lectureHours = lectureHours;
}
}
I used the service classes and controllers and the JPARepositories as usually. but the database table only contain 2 values fields only (staffID and lectureHours). as follows.
LecturerRepository.java
package com.example.backend.admin.Repositories;
import com.example.backend.admin.models.Lecturer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface LecturerRepository extends JpaRepository<Lecturer, Integer> {
}
LecturerController.java
#RestController
#RequestMapping("/lecturers")
public class LecturerController {
private static Logger logger = LoggerFactory.getLogger(LecturerController.class);
#Autowired
LecturerService lecturerService;
/**
* to insert a new lecturer
* #param lecturer new lecturer
* #return insert lecturer
*/
#PostMapping("/add")
public Lecturer addLecturer(#RequestBody Lecturer lecturer) {
Lecturer lecturer1 = null;
try {
lecturer1 = lecturerService.addLecturer(lecturer);
} catch (NullPointerException e) {
logger.error("check the payload, null pointer is throwing", e);
}
return lecturer1;
}
}
LecturerService.java
#Service
public class LecturerService {
#Autowired
LecturerRepository lecturerRepository;
/**
* to invoke save method in jpa
* #param lecturer new lecturer
* #return inserted lecturer
*/
public Lecturer addLecturer(Lecturer lecturer){
return lecturerRepository.save(lecturer);
}
}
I want to add all the fields of the Lecturer class into the database. So what should I do for that?
You need to annotate the abstract class with #MappedSuperclass, in this way your #Entity class will inherit all the attributes from the extended class.
I would like to get objects ResponsableEntity by id from the Database where they are saved. I use Spring-boot and hibernate for the first time and the slouches on other topics don't work in my project
Here are my code :
ResponsableEntity :
#Entity
#Table(name = "responsable")
public class ResponsableEntity {
/**
* Id of the responsable
*/
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/**
* First name of the responsable
*/
#Column(nullable=false)
private String firstName;
/**
* Lst name of the responsable
*/
#Column(nullable=false)
private String lastName;
/**
* Last latitude of the responsable position
*/
private Double latitude;
/**
* Last longitude of the responsable position
*/
private Double longitude;
/**
* All getters and setters [...]
*/
}
ResponsableDBRepository :
#Repository
public interface ResponsableDBRepository extends CrudRepository<ResponsableEntity, Long> {
}
ResponsableController (REST) :
#RestController
#RequestMapping("/responsable")
public class ResponsableController {
/**
* CRUD Repository atribut needed for the methods below
*/
private final ResponsableDBRepository responsableDBRepository;
private final ResponsableStatDBRepository responsableStatDBRepository;
/**
* Constructor
*
* #param responsableDBRepository CRUD repository for ResponsableEntity
* #param responsableStatDBRepository CRUD repository for ResponsableStatEntity
*/
#Autowired
public ResponsableController(ResponsableDBRepository responsableDBRepository, ResponsableStatDBRepository responsableStatDBRepository){
this.responsableDBRepository = responsableDBRepository;
this.responsableStatDBRepository = responsableStatDBRepository;
}
#GetMapping(path = "/get")
public #ResponseBody String getAllResponsable(){
//get object with id given
return "Returned";
}
}
I'd like that when we call this request, the entity is load from the database and an object ResponsableEntity is created with the infos saved in the database. I already tried most of the answer I found on other topics but most of the time my IDE told me he can't find the class required and it seems to be "default" classes from Hibernate and Spring
Thank you in advance for your answer !
Use this:-
ResponsableEntity responsableEntity = responsableDBRepository.findById(id);
I have a column name viewed_by on Firebase server
Test
|
|--viewed_by: 30
On the app I have a POJO class which has the member viewed_by
Test.class has member
private int viewed_by;
In onDataChange function when I receive the data, I get the Test object using the getValue function
Test t = dataSnapshot.getValue(Test.class);
But I get the value as 0 instead of 30.
If I change the field name from viewed_by to viewedBy (both on server and POJO class), I get the expected value (30)
Is it a parsing issue in getValue function? Or the field name are not supposed to have underscores in the name?
Jus figured it out, had to change the function names as well from ViewedBy to Viewed_By for it to work with viewed_by field
/**
*
* #return
* The viewed_by
*/
public int getViewed_By() {
return viewed_by;
}
/**
*
* #param viewed_by
* The viewed_by
*/
public void setViewed_By(int viewed_by) {
this.viewed_by = viewed_by;
}
Another option is to just declare the properties like below-using #PropertyName("property_name") in your model and use your getter and setter just like you like to do.
public class Actor {
#NonNull
#PrimaryKey
#ColumnInfo(name = "profile_id")
#PropertyName("profile_id")
private String profileId;
#ColumnInfo(name = "name")
#PropertyName("name")
private String name;
#PropertyName("profile_id")
public String getProfileId() {
return profileId;
}
#PropertyName("profile_id")
public void setProfileId(String profileId) {
this.profileId = profileId;
}
#PropertyName("name")
public String getName() {
return name;
}
}
Based on an archetype i created a java ee app. There is an included arquillian test that runs fine. it just calls a method on a #Stateless bean that persists an pre-made entity.
now i added some entity with some relations and i wrote a test for them. But on peristing any entity i get
Transaction is required to perform this operation (either use a transaction or extended persistence context)
I think i need to mark the testmethod with #Transactional but it seems not to be in class path.
Manually invoking the transaction on injected EntityManager yields another error.
So how to correctly setup such tests and dependencies.
EDIT As Grzesiek D. suggested here are some details. this is the entity (the one thta links others):
#Entity
public class Booking implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* internal id.
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
/**
* Used for optimistic locking.
*/
#Version
#Column(name = "version")
private int version;
/**
* A booking must have a project related.
*/
#ManyToOne
#JoinColumn(name = "project_id")
#NotNull
private Project project;
/**
* A booking must have an owner.
*/
#ManyToOne
#JoinColumn(name = "user_id")
#NotNull
private User owner;
/**
* A booking always has a start time.
*/
#Column
#NotNull
private Timestamp start;
/**
* A booking always has an end time.
*/
#Column
#NotNull
private Timestamp end;
/**
*
* #return true if start is befor end. false otherwise (if equal or after end).
*/
#AssertTrue(message = "Start must before end.")
public final boolean isStartBeforeEnd() {
return start.compareTo(end) < 0;
}
/**
* #return the id
*/
public final Long getId() {
return id;
}
/**
* #param id
* the id to set
*/
public final void setId(final Long id) {
this.id = id;
}
/**
* #return the version
*/
public final int getVersion() {
return version;
}
/**
* #param version
* the version to set
*/
public final void setVersion(final int version) {
this.version = version;
}
/**
* #return the project
*/
public final Project getProject() {
return project;
}
/**
* #param project
* the project to set
*/
public final void setProject(final Project project) {
this.project = project;
}
/**
* #return the owner
*/
public final User getOwner() {
return owner;
}
/**
* #param owner
* the owner to set
*/
public final void setOwner(final User owner) {
this.owner = owner;
}
/**
* #return the start
*/
public final Timestamp getStart() {
return start;
}
/**
* #param start
* the start to set
*/
public final void setStart(final Timestamp start) {
this.start = start;
}
/**
* #return the end
*/
public final Timestamp getEnd() {
return end;
}
/**
* #param end
* the end to set
*/
public final void setEnd(final Timestamp end) {
this.end = end;
}
//hashCode, equals, toString omitted here
}
Here is the test:
#RunWith(Arquillian.class)
public class BookingTest {
#Deployment
public static Archive<?> createDeployment() {
return ArquillianContainer.addClasses(Resources.class, Booking.class, Project.class, User.class);
}
#Inject
private EntityManager em;
#Test
public void createBooking() {
Booking booking = new Booking();
booking.setStart(new Timestamp(0));
booking.setEnd(new Timestamp(2));
User user = new User();
user.setName("Klaus");
booking.setOwner(user);
Project project = new Project();
project.setName("theOne");
project.setDescription("blub");
booking.setProject(project);
em.persist(booking);
System.out.println("here");
}
}
And here the exception:
javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I know it will work if i create a #Stateless bean and encapsulate the persist there but i want a direct test of entity's validation and i need a playground to evolve the data model.
In order to have transaction support in Arquillian tests you will need to bring in extension which enables this feature. In your case jta dependency should do the job.
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-transaction-jta</artifactId>
<scope>test</scope>
</dependency>
In addition, if you are using JBoss, you will need to provide its JNDI for UserTranscation, so put following section in your arquillian.xml:
<?xml version="1.0" ?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian" xsi:schemaLocation="http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="transaction">
<property name="manager">java:jboss/UserTransaction</property>
</extension>
</arquillian>
This way you can use #Transactional which comes from this extension's API.
I have a form that is representing a Role object. This role object can have one System object, which is selected via a drop-down list (form:select). It works perfectly except for one little snag: when editing the Role object the System object is not automatically selected on the list. From what I understand, it should be. Can anyone tell me why it isn't? Code is as follows:
Role class:
/**
* Represents a Role in the Database. Used for tracking purposes it allows us to
* find out what users and systems have certain roles. Role entity. #author
* MyEclipse Persistence Tools
*/
#Entity
#Table(name = "roles", catalog = "jess")
public class Role implements java.io.Serializable {
// Fields
private static final long serialVersionUID = -8599171489389401780L;
private Integer roleId;
#Valid
private System system;
...
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "SYSTEM_ID")
public System getSystem() {
return this.system;
}
public void setSystem(System system) {
this.system = system;
}
Controller:
#RequestMapping(value = "/" + MappingConstants.EDIT_ROLE + "/{id}",
method = RequestMethod.POST)
public ModelAndView getEditRoleForm(#PathVariable("id") Integer id)
{
Role r = new Role();
r.setRoleId(id);
Role role = roleService.searchAllRolesByID(r);
ModelAndView modelView = new ModelAndView(MappingConstants.ROLES_FOLDER + MappingConstants.EDIT_ROLE);
modelView.addObject(AttributeConstants.ROLE, role);
List<System> systems = systemService.searchAllSystems();
modelView.addObject(AttributeConstants.ALL_SYSTEMS, systems);
return modelView;
}
Property Editor:
public class SystemEditor extends PropertyEditorSupport
{
private final ISystemService systemService;
private static Logger logger = LogManager.getLogger(SystemEditor.class.getName());
public SystemEditor(ISystemService service)
{
super();
this.systemService = service;
}
/*
* (non-Javadoc)
* #see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
*/
public void setAsText(String text) throws IllegalArgumentException
{
try
{
if(logger.isDebugEnabled())
logger.debug("System value coming in the editor as: {}", text);
System system = systemService.searchAllSystemsById(Integer.valueOf(text));
setValue(system);
}
catch (Exception e)
{
logger.error("There was an error attempting to process the System from the Editor.", e);
}
}
/*
* (non-Javadoc)
* #see java.beans.PropertyEditorSupport#getAsText()
*/
public String getAsText()
{
System system = (System) getValue();
return system.getSystemId().toString();
}
}
And jsp:
<form:form method="post" action="${contextPath}/jess/saveeditedrole" modelAttribute="role">
<h2>${role.name}</h2>
<br/><br/>
<form:errors path="system"/>
<form:label path="system">System:</form:label>
<form:select path="system">
<form:options items="${systems}" itemValue="systemId" itemLabel="fullName"/>
</form:select>
In your form:select you're using System class. Make sure this class has a proper .equals() and hashCode() methods, otherwise Spring doesn't know how to tell which System object is selected.