I should read every value of Turn element in the input XML:
<Section type="report" startTime="0" endTime="182.952">
<Turn speaker="spk1" startTime="7.186" endTime="8.114">
<Sync time="7.186"/>un souci avec une inscription
</Turn>
<Turn speaker="spk2" startTime="8.114" endTime="8.533">
<Sync time="8.114"/>ouais
</Turn>
<Turn speaker="spk1 spk2" startTime="8.533" endTime="9.731">
<Sync time="8.533"/>
<Who nb="1"/>first value!
<Who nb="2"/>second value!
</Turn>
</Section>
So I used JAXB and made the following classes:
Section:
#XmlRootElement(name="Section")
public class Section {
private List<Turn> turn;
#XmlElement(name="Turn")
public List<Turn> getTurn() {
if(turn == null){
turn = new ArrayList<Turn>();
}
return turn;
}
public void setTurn(List<Turn> turn) {
this.turn = turn;
}
}
Turn:
#XmlRootElement(name="Turn")
public class Turn {
private String speaker;
private float startTime;
private float endTime;
private Sync sync;
private String content;
private List<Who> whoList;
#XmlAttribute
public String getSpeaker() {
return speaker;
}
public void setSpeaker(String speaker) {
this.speaker = speaker;
}
public float getStartTime() {
return startTime;
}
#XmlAttribute
public void setStartTime(float startTime) {
this.startTime = startTime;
}
#XmlAttribute
public float getEndTime() {
return endTime;
}
public void setEndTime(float endTime) {
this.endTime = endTime;
}
#XmlValue
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
But when I want to read for example the value of Turn where speaker equals "spk1 spk2", the method getContent of Turn return only "second value!".. How i can get all content with "first value!" ?
I know is not allowed to set XmlElement with XmlValue for one Element, but I have no choice, the xml files are like that, and I should work with many files like that..
Thanks in advance :)
So you deal with mixed content. Have a look to the other question how-to-deal-with-jaxb-complextype-with-mixedcontent-data and jaxb-xmlmixed-usage-for-reading-xmlvalue-and-xmlelement. It would be manageable with the annotation #XmlMixed for your Turn class. Then, I'm not quite sure if you need the getter and setter methods for the content.
I think you problem comes from your declaration of #XmlElement(name="Turn"). If you have a look to the following tutorial from Vogella, you'll see he is using a wrapper for its list thanks to the annotation XmlElementWrapper and sets the annotations at the declaration of the list, not before the method, as following:
// XmLElementWrapper generates a wrapper element around XML representation
#XmlElementWrapper(name = "bookList")
// XmlElement sets the name of the entities
#XmlElement(name = "book")
private ArrayList bookList;
In your case, I think JAXB manage an object when you expect it to deal with a list of objects.
Related
I graphql-spqr, java.util.Date is defined as Scalar. Is it possible to overwrite the serialization/deserialization of java.util.Date to get a different String representation of the date?
The ScalarStrategy mentioned in this answer was removed with the latest release.
public class Order {
private String id;
private Date orderDate; //GraphQLScalarType "Date"
public Order() {
}
public Order(String id, String bookId, Date orderDate) {
this.id = id;
this.orderDate = orderDate;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
}
GraphQL Response:
{
"data": {
"createOrder": {
"id": "74e4816c-f850-4d63-9855-e4601fa125f4",
"orderDate": "2019-05-26T08:25:01.349Z", // --> 2019-05-26
}
}
}
ScalarStrategy isn't the proper way to achieve what you want. When you want to change how a Java type gets mapped to GraphQL, you normally provide a new (or customize an existing) TypeMapper.
Take a look at the existing Date scalar implementation and implement your own in a similar way. Then implement a custom TypeMapper that simply always returns a static instance of that scalar from both toGraphQLType and toGraphQLInputType methods.
public class CustomTypeMapper implements TypeMapper {
private static final GraphQLScalarType GraphQLCustomDate = ...;
#Override
public GraphQLOutputType toGraphQLType(...) {
return GraphQLCustomDate;
}
#Override
public GraphQLInputType toGraphQLInputType(...) {
return GraphQLCustomDate;
}
#Override
public boolean supports(AnnotatedType type) {
return type.getType() == Date.class; // This mapper only deals with Date
}
}
To register it, call generator.withTypeMappers(new CustomTypeMapper().
That said, since you're only trying to cut off the time part, you'd ideally use LocalDate here. You can make SPQR do that transparently by registering a TypeAdapter (which is nothing but a mapper + converter) but a simple mapper as explained above is a more efficient solution in your case. If you still decide to go the adapter way, you can inherit AbstractTypeAdapter<Date, LocalDate> and implement the conversion logic (should be trivial). Register via generator.withTypeAdapters or by registering it as a mapper and converters separately.
I have used One-to-Many Mapping in my project. I have stored a list of clicks for every user.
But when I retrieve the list by calling getClicks() methodm Hibernate returns list in different format.
Something like this.
"[com.zednx.tech.persistence.Click#29df9a77]"
So I tried Reading Every value from the list and assign to a new List.
List<Click> clicks=new ArrayList<Click>();
for(Click c: e.getClicks()){
Click temp = new Click();
temp.setAff_source(c.getAff_source());
temp.setCb_to_award(c.getCb_to_award());
temp.setCb_type(c.getCb_type());
clicks.add(temp);
}
But when i print the items of new List it stills prints the same way.
I need to build a JSON from the resulting String of this list.
So if the list is returned in format, it wont help me.
I couldn't find anything regarding this except How to pretty print Hibernate query results?
I tried Arrays.ToString(Object o). But it doesn't work.
GSON builder part-
Gson gson = new GsonBuilder()
.registerTypeAdapter(Click.class, new MyTypeAdapter<Click>())
.create();
List<Click> clicks=new ArrayList<Click>();
for(Click c: e.getClicks()){
Click temp = new Click();
temp.setAff_source(c.getAff_source());
temp.setCb_to_award(c.getCb_to_award());
temp.setCb_type(c.getCb_type());
temp.setCom_to_recieve(c.getCom_to_recieve());
temp.setStore_name(c.getStore_name());
temp.setT_date(c.getT_date());
temp.setT_status(c.getT_status());
temp.setT_ticket(c.getT_ticket());
temp.setUid(c.getUid());
System.out.println(c.toString());
clicks.add(temp);
}
String json = gson.toJson(clicks, Click.class);
Click.java
#Entity
#Table(name="click")
public class Click {
#Id
#Column(name="t_ticket")
private String t_ticket;
#Column(name="uid",nullable=false)
private long uid;
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
#ManyToOne
#JoinColumn(name="uid",
insertable=false, updatable=false,
nullable=false)
private Earning earning;
#Column(name="store_name")
private String store_name;
#Column(name="t_status")
private String t_status;
#Column(name="aff_source")
private String aff_source;
#Column(name="com_to_recieve")
private float com_to_recieve;
#Column(name="t_date")
private Date t_date;
#Column(name="cb_to_award")
private float cb_to_award;
#Column(name="cb_type")
private String cb_type;
public String getT_ticket() {
return t_ticket;
}
public void setT_ticket(String t_ticket) {
this.t_ticket = t_ticket;
}
public Earning getEarning() {
return earning;
}
public void setEarning(Earning earning) {
this.earning = earning;
}
public String getStore_name() {
return store_name;
}
public void setStore_name(String store_name) {
this.store_name = store_name;
}
public String getT_status() {
return t_status;
}
public void setT_status(String t_status) {
this.t_status = t_status;
}
public String getAff_source() {
return aff_source;
}
public void setAff_source(String aff_source) {
this.aff_source = aff_source;
}
public float getCom_to_recieve() {
return com_to_recieve;
}
public void setCom_to_recieve(float com_to_recieve) {
this.com_to_recieve = com_to_recieve;
}
public Date getT_date() {
return t_date;
}
public void setT_date(Date t_date) {
this.t_date = t_date;
}
public float getCb_to_award() {
return cb_to_award;
}
public void setCb_to_award(float cb_to_award) {
this.cb_to_award = cb_to_award;
}
public String getCb_type() {
return cb_type;
}
public void setCb_type(String cb_type) {
this.cb_type = cb_type;
}
Any Help is appreciated.
You need to implement a toString method, as your current Click class likely doesn't have one, so it just prints as the name of the class and instance identifier.
Okay, I could solve my problem finally.
I made another POJO without any annotations and Mapped the List items to that POJO class.
I think the problem was with Annotation of mapping on another class which I had in original POJO.
Also getString() method only helps in changing format of identifier. So basically it has nothing to do with JSON building unless you format getString() in form of JSON.
Hope it helps. If anyone wants new temp POJO I made I can post it if requested.
Thanks.
The Code Below allows me to write an Object into an XML file.
public class BathGuest{
private String name = "";
private DateMinutesHours wakeUpTime;
private int duration = 0;
private DateMinutesHours _plannedTime;
#XmlElement(name ="plannedTime")
public DateMinutesHours get_plannedTime() {
return _plannedTime;
}
#XmlElement(name = "ID")
public String getName() {
return _name;
}
...
}
The problem I have is, that birthday is an other Class to handle my timeoperations. So the result of my XML File, is not really what i expected.
What I get is:
<bathroomEntity>
<duration>3</duration>
<ID>Walter</ID>
<startTime>
<totalMinutes>481</totalMinutes>
</startTime>
<plannedTime>
<totalMinutes>485</totalMinutes>
</plannedTime>
</bathroomEntity>
And what I want is:
<bathroomEntity>
<duration>3</duration>
<ID>Walter</ID>
<startTime>08:10</startTime>
<plannedTime>08:50</plannedTime>
</bathroomEntity>
How can I reach the Second XMl-File?
If you annotate the totalMinutes property on the DateMinutesHours class with #XmlValue then you will get the behaviour you are lookiing for.
I am serializing Diagram class to GAE Datastore using Objectify. I can update (serialize) all the fields as many times as I want, except Integer arrowTypeId, that is only updated once, and after that keeps always the same value. If I leave the app and run it again, I can update again that value, but only once.
To update arroyTypeId I am calling sendDatabaseUpdateDiagramArrows(). This is what happens:
I call sendDatabaseUpdateDiagramArrows() with value 1
I set that value to the DiagramProxy.setArrowTypeId().
As a test, I change the diagram title to DiagramProxy.getArrowTypeId()
I call save()
On the DAO save(), the wrong value of ArrowTypeId is received (keeps the old one), but surprisingly, the Title has the right ArrowTypeId stored from step 3)
Changes are serialized with this problem. No exceptions are displayed.
Note that I am able to update ArrowTypeId value the first time, from default value 1 to 2. Buth the next time keeps always value 2.
Edit: If I change arrowTypeId to a String, I have the same issue.
DatabaseUtils.java
public static DiagramProxy sendDatabaseUpdateDiagramArrows(DialectiveRequestFactory requestFactory, Integer value, DiagramProxy cellDiagramProxy)
{
DiagramRequest diagramRequest = requestFactory.diagramRequest();
DiagramProxy newDiagramProxy = diagramRequest.edit(cellDiagramProxy);
Date date = new Date();
newDiagramProxy.setArrowTypeId(value);
newDiagramProxy.setTitle(Integer.toString(newDiagramProxy.getArrowTypeId()));
diagramRequest.save(newDiagramProxy).fire();
return cellDiagramProxy;
}
Diagram.java
#Entity
public class Diagram extends DatastoreObject{
#Indexed private String diagramId;
private String title;
private Integer arrowTypeId;
public String get_id() {
return diagramId;
}
public void set_id(String diagramId) {
this.diagramId = diagramId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getArrowTypeId() {
return arrowTypeId;
}
public void setArrowTypeId(Integer arrowTypeId) {
this.arrowTypeId = arrowTypeId;
}
}
DiagramProxy.java
#ProxyFor(value = Diagram.class, locator = ObjectifyLocator.class)
public interface DiagramProxy extends EntityProxy{
void set_id(String id);
void setTitle(String title);
void setArrowTypeId(Integer arrowTypeId);
Integer getArrowTypeId();
String get_id();
String getTitle();
}
DiagramDao.java
public class DiagramDao extends ObjectifyDao<Diagram>{
public void save(Diagram diagram)
{
this.put(diagram);
} }
Let me guess :) as I don't have experience with GAE datastore.
I don't get the point, why you make
#Indexed private String diagramId;
but getter and setter with non-standard names:
public String get_id() {
return diagramId;
}
public void set_id(String diagramId) {
this.diagramId = diagramId;
}
I'd rather go for:
#Indexed private String diagramId;
public String getDiagramId() {
return diagramId;
}
public void setDiagramId(String diagramId) {
this.diagramId = diagramId;
}
One more thing is that DiagramRequest code has not been published, maybe that could help in seeing the problem.
I want to marshal/unmarshal 2 custom types. And the type 1 has a List. Marshalling works as expected - I see a separate element for every type2 element in the list, but when I try to unmarshal it this doesn't work.
Workflow
#XmlRootElement
public class Workflow {
private String userEmail;
private List<WorkflowStep> steps = new ArrayList<WorkflowStep>(5);
//required by jaxb
public Workflow() {
}
public void setSteps(List<WorkflowStep> steps) {
this.steps = steps;
}
public List<WorkflowStep> getSteps() {
//do a defensive copy
return new ArrayList<WorkflowStep>(steps);
}
public void setUserEmail(String email) {
userEmail = email;
}
public String getUserEmail() {
return userEmail;
}
}
WorkflowStep
#XmlRootElement
public class WorkflowStep {
private int cpu = 1;
private int mem = 1000;
private Map<String, String> parameters = Collections.emptyMap();
public WorkflowStep() {
}
public void setCpu(int numCores) {
cpu = numCores;
}
public int getCpu() {
return cpu;
}
public void setMem(int mb) {
mem = mb;
}
public int getMem() {
return mem;
}
}
Here is an example output if I access the web service from a browser:
<workflow>
<steps>
<cpu>1</cpu>
<inputId>237</inputId>
<mem>1000</mem>
<parameters/>
<status>NOT-YET-STARTED</status>
<stepId>1509</stepId>
<submoduleId>0</submoduleId>
<workflowId>797</workflowId>
</steps>
<steps>
<cpu>1</cpu>
<inputId>364</inputId>
<mem>1000</mem>
<parameters/>
<status>NOT-YET-STARTED</status>
<stepId>1510</stepId>
<submoduleId>3</submoduleId>
<workflowId>797</workflowId>
</steps>
<userEmail>foo#bar.com</userEmail>
<workflowId>797</workflowId>
<workflowName>test-name</workflowName>
</workflow>
WorkflowStep is marshalled/unmarshalled successfully but a List cannot be unmarshalled why is that? Nor the application server, nor the REST client receive any errors or exceptions, the client just ignores the list of WorkflowSteps? From the above example output I'd expect that every element would be converted into an object of type WorkflowStep and then will automatically be added to the List?
The problem is with this method:
public List<WorkflowStep> getSteps() {
//do a defensive copy
return new ArrayList<WorkflowStep>(steps);
}
Your JAXB implementation checks if there is already a List for this method, and if there is it uses it. The List you are returning is not held by the object you are unmarshalling, so after the unmarshal operation the List is lost.
Option #1 - Change the getSteps() Method
public List<WorkflowStep> getSteps() {
//don't do a defensive copy
return steps;
}
Option #2 - Use Field Access
You could change this your specify that JAXB should use field access.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Workflow {
...
}
For more information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html