Javafx dynamic Table - dynamic

I want create dynamic table with TableView class.
I send to contractor the number of columns (int), columns name (String[]) and rows (Student), but I can't deal with that.
How I need to define the TableColumn for each one of columns?
public class DynamicTable extends TableView<Student>{
private ObservableList<Student> data;
private int columnCount;
private String[] columnName;
private TableView<Student> tableView;
DynamicTable(){
}
DynamicTable(int columnCount, Student[] rows, String[] columnName){
this.columnName=columnName;
this.columnCount=columnCount;
data = FXCollections.observableArrayList();
setData(rows);
}
public void buildTable(){
for(int i=0 ; i<columnCount; i++){
final int j=i;
TableColumn<Student,String> col = new TableColumn<Student,String>(columnName[i]);
//col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Student,String>, ObservableValue<String>>() {
//#Override
//public ObservableValue<String> call(
// CellDataFeatures<Student, String> param) {
// return new SimpleStringProperty(param.getValue().getAddress());
// }
//});
tableView.getColumns().addAll(col);
tableView.setItems(data);
}
}
public void setData(Student[] rows){
data.setAll(rows);
}
public String[] getColumnName(){
return this.columnName;
}
}
I be glad for receiving your answer.
Edit: Student class:
public class Student implements Externalizable
{
private final SimpleIntegerProperty ID;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty address;
private final SimpleObjectProperty<Date> birthDate;
private final SimpleStringProperty department;
private final SimpleIntegerProperty pointsAmount;
private final SimpleObjectProperty<Date> startStudyingDate;
private final SimpleIntegerProperty failedAmount;
private final SimpleDoubleProperty average;
private final SimpleIntegerProperty lavelByGrade;
private final SimpleStringProperty pic;
public Student(){
this.ID = new SimpleIntegerProperty();
this.firstName= new SimpleStringProperty();
this.lastName= new SimpleStringProperty();
this.address= new SimpleStringProperty();
this.birthDate= new SimpleObjectProperty<Date>();
this.department= new SimpleStringProperty();
this.pointsAmount= new SimpleIntegerProperty();
this.startStudyingDate= new SimpleObjectProperty<Date>();
this.failedAmount= new SimpleIntegerProperty();
this.average= new SimpleDoubleProperty();
this.lavelByGrade= new SimpleIntegerProperty();
this.pic = new SimpleStringProperty();
}
public Student(int ID, String firstName, String lastName, String address,
Date birthDate, String department,
int pointsAmount, Date startStudyingDate, int failedAmount,
double average, int lavelByGrade, String pic){
this.ID= new SimpleIntegerProperty(ID);
this.firstName= new SimpleStringProperty(firstName);
this.lastName= new SimpleStringProperty(lastName);
this.address= new SimpleStringProperty(address);
this.birthDate= new SimpleObjectProperty<Date>(birthDate);
this.department= new SimpleStringProperty(department);
this.pointsAmount= new SimpleIntegerProperty(pointsAmount);
this.startStudyingDate= new SimpleObjectProperty<Date>(startStudyingDate);
this.failedAmount= new SimpleIntegerProperty(failedAmount);
this.average= new SimpleDoubleProperty(average);
this.lavelByGrade= new SimpleIntegerProperty(lavelByGrade);
this.pic = new SimpleStringProperty(pic);
}
public int getID() {
return ID.get();
}
public void setID(int ID) {
this.ID.set(ID);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getAddress() {
return address.get();
}
public void setAddress(String address) {
this.address.set(address);
}
public Date getBirthDate() {
return birthDate.get();
}
public void setBirthDate(Date birthDate) {
this.birthDate.set(birthDate);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String department) {
this.department.set(department);
}
public int getPointsAmount() {
return pointsAmount.get();
}
public void setPointsAmount(int pointsAmount) {
this.pointsAmount.set(pointsAmount);
}
public Date getStartStudyingDate() {
return startStudyingDate.get();
}
public void setStartStudyingDate(Date startStudyingDate) {
this.startStudyingDate.set(startStudyingDate);
}
public int getFailedAmount() {
return failedAmount.get();
}
public void setFailedAmount(int failedAmount) {
this.failedAmount.set(failedAmount);
}
public double getAverage() {
return average.get();
}
public void setAverage(Double average) {
this.average.set(average);
}
public int getLavelByGrade() {
return lavelByGrade.get();
}
public void setLavelByGrade(int lavelByGrade) {
this.lavelByGrade.set(lavelByGrade);
}
public String getPic() {
return pic.get();
}
public void setPic(String pic) {
this.pic.set(pic);
}
#Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setID(in.readInt());
setFirstName((String)in.readObject());
setLastName((String)in.readObject());
setAddress((String)in.readObject());
setBirthDate((Date)in.readObject());
setDepartment((String)in.readObject());
setPointsAmount(in.readInt());
setStartStudyingDate((Date)in.readObject());
setFailedAmount(in.readInt());
setAverage(in.readDouble());
setLavelByGrade(in.readInt());
setPic((String)in.readObject());
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getID());
out.writeObject(getFirstName());
out.writeObject(getLastName());
out.writeObject(getAddress());
out.writeObject(getBirthDate());
out.writeObject(getDepartment());
out.writeInt(getPointsAmount());
out.writeObject(getStartStudyingDate());
out.writeInt(getFailedAmount());
out.writeDouble(getAverage());
out.writeInt(getLavelByGrade());
out.writeObject(getPic());
}
}

First, you need to add property accessor methods to your Student class:
public class Student {
private final SimpleStringProperty firstName ;
// etc ...
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
// Add methods like this:
public StringProperty firstNameProperty() {
return firstName ;
}
// ... etc
}
Then your cell value factory will look something like this:
TableColumn<Student,String> col = new TableColumn<Student,String>(columnName[i]);
col.setCellValueFactory(cellData -> {
Student student = cellData.getValue();
return student.xxxProperty();
});
Where you replace xxxProperty() with the actual property whose value you want to display in that column.

Related

When arraylist prints objects from 2 classes how to make it print objects from only 1 class

I have this class called Training that extends the other 2 classes
public class Training{
public int workoutTime;
public String typeOfWorkout;
public Training(){
}
public Training(int workoutTime, String typeOfWorkout) {
this.workoutTime = workoutTime;
this.typeOfWorkout = typeOfWorkout;
}
public int getWorkoutTime() {
return workoutTime;
}
public String getTypeOfWorkout() {
return typeOfWorkout;
}
public class Anaerobic extends Training{
public int noOfSets;
public Anaerobic(int workoutTime, String typeOfWorkout, int noOfSets) {
super(workoutTime, ypeOfWorkout);
this.noOfSets = noOfSets;
}
public int getNoOfSets() {
return noOfSets;
}
public class Aerobic extends Training{
public Anaerobic(int workoutTime, String typeOfWorkout) {
super(workoutTime, ypeOfWorkout);
}
public static void main(String[] args) {
Anaerobic anaerobic = new Anaerobic(60, "Strength", 4);
Anaerobic anaerobic1 = new Anaerobic(75, "Strength", 6);
Anaerobic anaerobic2 = new Anaerobic(90, "Strength", 4);
Anaerobic anaerobic3 = new Anaerobic(60, "Strength", 5);
Aerobic aerobic = new Aerobic(60, "Cardio");
ArrayList<Training> list = new ArrayList<>();
list.add(anaerobic);
list.add(anaerobic1);
list.add(anaerobic2);
list.add(anaerobic3);
list.add(aerobic);
showList(list);
And now i have to make a new list and make it print object from either Anaerobic or Aerobic but i have to use the already generated list so i dont know how to do it.
I tried this.
ArrayList listAnaerobic = new ArrayList<>(list);
showListAnaerobic(listAnaerobic);
}
}
public static void showList(ArrayList<Training> lista) {
for (Training list : lista) {
System.out.println(list);
}
public static void showListAnaerobic(ArrayList<Anaerobic> lista) {
for (Anaerobic list : lista) {
System.out.println(list);
}
}

Hazelcast: Does Portable Serialization needs objects to be shared between client and server?

I am getting the below exception:
Could not find PortableFactory for factory-id: 1
com.hazelcast.nio.serialization.HazelcastSerializationException: Could
not find PortableFactory for factory-id: 1
On the client side I have the following code:
public class ClientTest {
public static void main(String[] args) {
List<String> nodes = new ArrayList<String>();
nodes.add("localhost:5701");
ClientConfig clientConfig = new ClientConfig();
ClientNetworkConfig networkConfig = new ClientNetworkConfig();
networkConfig.setAddresses(nodes);
clientConfig.setNetworkConfig(networkConfig);
SerializationConfig serCong = clientConfig.getSerializationConfig();
serCong.addPortableFactory(1, new UserFactoryImpl());
serCong.setPortableVersion(1);
HazelcastInstance hzClient1 = HazelcastClient.newHazelcastClient(clientConfig);
IMap<String, User> map = hzClient1.getMap("user");
System.out.println(map.size() + "hiten");
User user1 = new User();
user1.setFirstName("hiten");
user1.setLastName("singh");
map.put("1", user1);
//hz1.getLifecycleService().terminate();
System.out.println(map.size() + "after");
User user2 = new User();
user2.setFirstName("hiten1");
user2.setLastName("singh1");
map.put("2", user2);
UserEntryProcessor entryProc = new UserEntryProcessor();
User userRes = (User)map.executeOnKey("1", entryProc);
}
static class UserEntryProcessor implements EntryProcessor<String, User>, HazelcastInstanceAware {
private transient HazelcastInstance hazelcastInstance;
#Override
public Object process(Entry<String, User> entry) {
User user = entry.getValue();
if(user != null) {
System.out.println(user.getFirstName());
}
return user;
}
#Override
public EntryBackupProcessor<String, User> getBackupProcessor() {
return null;
}
#Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.hazelcastInstance = hazelcastInstance;
}
}
static class UserFactoryImpl implements PortableFactory{
public final static int USER_PORTABLE_ID = 1;
public final static int FACTORY_ID = 1;
public Portable create(int classId) {
switch (classId) {
case USER_PORTABLE_ID:
return new User();
}
return null;
}
}
static class User implements Portable {
private String firstName;
private String lastName;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Override
public int getFactoryId() {
return UserFactoryImpl.FACTORY_ID;
}
#Override
public int getClassId() {
return UserFactoryImpl.USER_PORTABLE_ID;
}
#Override
public void writePortable(PortableWriter writer) throws IOException {
writer.writeUTF("first_name", firstName);
writer.writeUTF("last_name", lastName);
}
#Override
public void readPortable(PortableReader reader) throws IOException {
firstName = reader.readUTF("first_name");
lastName = reader.readUTF("last_name");
}
}
}
Yes it does, just as you figured out the factory and the classes need to be available. Currently there is no built-in solution to not share classes for more sophisticated use cases than simple gets / puts. I have JSON support and some other ideas cooking but nothing really done yet.

Embedded Neo4j delete node and Lucene legacy indexing - node_auto_indexing out of sync issue

I'm trying to delete node with fields in node_auto_indexing.
When I try to delete node using repository.delete(id).
Right after that I'm trying to get deleted Node by its id and I get following exception:
java.lang.IllegalStateException: This index (Index[__rel_types__,Relationship]) has been marked as deleted in this transaction
at org.neo4j.index.impl.lucene.LuceneTransaction$DeletedTxDataBoth.illegalStateException(LuceneTransaction.java:475)
at org.neo4j.index.impl.lucene.LuceneTransaction$DeletedTxDataBoth.removed(LuceneTransaction.java:470)
at org.neo4j.index.impl.lucene.LuceneTransaction.remove(LuceneTransaction.java:112)
at org.neo4j.index.impl.lucene.LuceneXaConnection.remove(LuceneXaConnection.java:116)
at org.neo4j.index.impl.lucene.LuceneIndex.remove(LuceneIndex.java:215)
at org.springframework.data.neo4j.support.typerepresentation.AbstractIndexBasedTypeRepresentationStrategy.remove(AbstractIndexBasedTypeRepresentationStrategy.java:113)
at org.springframework.data.neo4j.support.typerepresentation.AbstractIndexBasedTypeRepresentationStrategy.preEntityRemoval(AbstractIndexBasedTypeRepresentationStrategy.java:100)
at org.springframework.data.neo4j.support.mapping.EntityRemover.removeRelationship(EntityRemover.java:63)
at org.springframework.data.neo4j.support.mapping.EntityRemover.removeNode(EntityRemover.java:51)
at org.springframework.data.neo4j.support.mapping.EntityRemover.removeNodeEntity(EntityRemover.java:45)
at org.springframework.data.neo4j.support.mapping.EntityRemover.remove(EntityRemover.java:85)
at org.springframework.data.neo4j.support.Neo4jTemplate.delete(Neo4jTemplate.java:267)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.delete(AbstractGraphRepository.java:276)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.delete(AbstractGraphRepository.java:282)
Also, when I'm trying to delete node via Cypher query
#Query("MATCH ()-[r]-(p:Product) WHERE id(p) = {productId} DELETE r, p")
void deleteProduct(#Param("productId") Long productId);
I'm getting another exception after looking this deleted Node by its Id:
java.lang.IllegalStateException: No primary SDN label exists .. (i.e one starting with _)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:126)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:39)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:36)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:26)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:102)
at org.springframework.data.convert.DefaultTypeMapper.getDefaultedTypeToBeUsed(DefaultTypeMapper.java:165)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:142)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:78)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:189)
at org.springframework.data.neo4j.support.Neo4jTemplate.createEntityFromState(Neo4jTemplate.java:224)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.createEntity(AbstractGraphRepository.java:62)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.findOne(AbstractGraphRepository.java:127)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.delete(AbstractGraphRepository.java:282)
How to correctly delete node that participates in Lucene Legacy Indexing node_auto_indexing ? How to remove this Node from Lucene index ?
UPDATED:
This is my Neo4jConfig:
#Configuration
#EnableNeo4jRepositories(basePackages = "com.example")
#EnableTransactionManagement
public class Neo4jConfig extends Neo4jConfiguration implements BeanFactoryAware {
#Resource
private Environment environment;
private BeanFactory beanFactory;
public Neo4jConfig() {
setBasePackage("com.example");
}
#Bean(destroyMethod = "shutdown")
public GraphDatabaseService graphDatabaseService() {
GraphDatabaseService graphDb = new GraphDatabaseFactory()
.newEmbeddedDatabaseBuilder("target/example-test-db")
.setConfig(GraphDatabaseSettings.node_keys_indexable, "name,description")
.setConfig(GraphDatabaseSettings.node_auto_indexing, "true")
.newGraphDatabase();
return graphDb;
}
/**
* Hook into the application lifecycle and register listeners that perform
* behaviour across types of entities during this life cycle
*
*/
#Bean
protected ApplicationListener<BeforeSaveEvent<BaseEntity>> beforeSaveEventApplicationListener() {
return new ApplicationListener<BeforeSaveEvent<BaseEntity>>() {
#Override
public void onApplicationEvent(BeforeSaveEvent<BaseEntity> event) {
BaseEntity entity = event.getEntity();
if (entity.getCreateDate() == null) {
entity.setCreateDate(new Date());
} else {
entity.setUpdateDate(new Date());
}
}
};
}
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}
Base entity for entities in the project:
public class BaseEntity {
private Date createDate;
private Date updateDate;
public BaseEntity() {
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
}
and the Vote entity that I tried to delete:
#NodeEntity
public class Vote extends BaseEntity {
private static final String VOTED_ON = "VOTED_ON";
private final static String VOTED_FOR = "VOTED_FOR";
private static final String CREATED_BY = "CREATED_BY";
#GraphId
private Long id;
#RelatedTo(type = VOTED_FOR, direction = Direction.OUTGOING)
private Decision decision;
#RelatedTo(type = VOTED_ON, direction = Direction.OUTGOING)
private Criterion criterion;
#RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
private User author;
private double weight;
private String description;
public Vote() {
}
public Vote(Decision decision, Criterion criterion, User author, double weight, String description) {
this.decision = decision;
this.criterion = criterion;
this.author = author;
this.weight = weight;
this.description = description;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Decision getDecision() {
return decision;
}
public void setDecision(Decision decision) {
this.decision = decision;
}
public Criterion getCriterion() {
return criterion;
}
public void setCriterion(Criterion criterion) {
this.criterion = criterion;
}
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Vote vote = (Vote) o;
if (id == null)
return super.equals(o);
return id.equals(vote.id);
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : super.hashCode();
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
Thanks to #MichaelHunger and Neo4j this issue has been fixed in Neo4j 2.2.2 and SDN 3.4.0.M1

PersistenceException: ERROR executing DML bindLog when Updating an Object

Good day! I have two objects: Tag and RelatedTag. The Tag can have many RelatedTags (which is also a Tag). Saving the Tag with its related tags works fine. But when I update the Tag, it has an error saying
[PersistenceException: ERROR executing DML bindLog[] error[Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.RELATED_TAG(ID)"; SQL statement:\n insert into related_tag (id, tag_id, relationship, related_notes) values (?,?,?,?) [23505-172]]]
Here is Tag model:
package models;
import java.util.*;
import javax.persistence.*;
import javax.validation.*;
import play.data.Form;
import play.data.validation.Constraints.*;
import play.db.ebean.*;
import play.db.ebean.Model.Finder;
import scala.Int;
#Entity
public class Tag extends Model{
#Id
private int id;
#Required
#MaxLength(value=100)
private String name;
#MaxLength(value=200)
private String notes;
#OneToMany(cascade=CascadeType.ALL)
public List<RelatedTag> relatedTags = new ArrayList<RelatedTag>();
public static Finder<Integer, Tag> find = new Finder(Int.class, Tag.class);
public Tag() {
}
public Tag(String name, String notes){
this.name = name;
this.notes = notes;
}
public Tag(int id, String name, String notes, List<RelatedTag> relatedTags) {
this.id = id;
this.name = name;
this.notes = notes;
this.relatedTags = relatedTags;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public List<RelatedTag> getRelatedTags() {
return relatedTags;
}
public void setRelatedTags(List<RelatedTag> relatedTags) {
this.relatedTags = relatedTags;
}
public static List<Tag> all() {
return find.all();
}
public static void create(Tag tag){
tag.save();
}
public static void delete(int id){
find.ref(id).delete();
}
public static void update(int id, Tag tag) {
tag.update(id); // updates this entity, by specifying the entity ID
}
public static boolean exists(Tag newTag) {
for(Tag allTags : Tag.find.all()) {
if(allTags.getName().equals(newTag.getName()))
return true;
}
return false;
}
}
And here is the RelatedTag model:
package models;
import java.util.*;
import javax.persistence.*;
import javax.validation.*;
import play.data.Form;
import play.data.validation.Constraints.*;
import play.db.ebean.*;
import play.db.ebean.Model.Finder;
import scala.Int;
#Entity
public class RelatedTag extends Model {
#Id
private int id;
private String relationship;
private String relatedNotes;
public RelatedTag() {}
public RelatedTag(int id, String relationship, String relatedNotes) {
this.id = id;
this.relationship = relationship;
this.relatedNotes = relatedNotes;
}
public void setId(int id){
this.id = id;
}
public void setRelationship(String relationship){
this.relationship = relationship;
}
public void setRelatedNotes(String relatedNotes) {
this.relatedNotes = relatedNotes;
}
public int getId(){
return id;
}
public String getRelationship(){
return relationship;
}
public String getRelatedNotes() {
return relatedNotes;
}
public static boolean exists(String tagRelated) {
for(Tag tag : Tag.find.all()) {
if(tagRelated.equals(tag.getName()))
return true;
}
return false;
}
public static RelatedTag findByLabel(String tagRelated, String relation, String relatedNotes) {
RelatedTag relatedTag = null;
for(Tag tag : Tag.find.all()) {
if(tagRelated.equals(tag.getName())) {
relatedTag = new RelatedTag(tag.getId(), relation, relatedNotes);
}
}
return relatedTag;
}
public static Tag findTag(int id) {
for(Tag tag : Tag.find.all()) {
if(id == tag.getId())
return tag;
}
return null;
}
}
When I run this (in which I update a Tag), the error happens.
private static void reciprocate(Tag tag) {
List<Tag> peers = new ArrayList<Tag>();
for (RelatedTag rt : tag.getRelatedTags()) {
if(rt.getRelationship().equals("peer"))
peers.add(RelatedTag.findTag(rt.getId()));
}
for(RelatedTag rt : tag.getRelatedTags()) {
int relTemp = 0;
String relation = new String();
if (rt.getRelationship().equals("parent"))
relTemp = 1;
if (rt.getRelationship().equals("child"))
relTemp = 2;
if (rt.getRelationship().equals("peer"))
relTemp = 3;
switch(relTemp) {
case 1: relation = "child"; break;
case 2: relation = "parent"; break;
case 3: relation = "peer"; break;
}
Tag related = new Tag();
related = Tag.find.byId(RelatedTag.findTag(rt.getId()).getId());
List<RelatedTag> available = new ArrayList<RelatedTag>();
List<String> availableName = new ArrayList<String>();
for (RelatedTag rt2 : related.getRelatedTags()) {
availableName.add(RelatedTag.findTag(rt2.getId()).getName());
}
if(availableName.contains(tag.getName())) {
for(RelatedTag rt2 : related.getRelatedTags()) {
if(!RelatedTag.findTag(rt2.getId()).getName().equals(tag.getName())) {
available.add(rt2);
}
}
}
available.add(RelatedTag.findByLabel(
tag.getName(), relation,
rt.getRelatedNotes()));
related.setRelatedTags(available);
related.update(related.getId()); //HERE
}
}
Please help me figure this out. After the first rt has been iterated, there goes the error but it saves its related tag. Thank you very much.
Your method RelatedTag#findByLabel always creates new RelatedTags with the IDs of the Tag class; if you have 2 related tags for the same tag, it will produce 2 related tags with the same ID.
Look into #GeneratedValue and EntityManager#createQuery.

Deserialize JSON with Gson - Expected BEGIN_OBJECT but was String - Reddit's JSON

I'm trying to deserialize JSON from Reddit that you can obtain by appending .json to the url. An example would be:
http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top
However, I am getting the error message:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 9765
At line 1 column 9765 in the json there is the following code: "replies": "", whereas normally this would contain an object like this: replies: {
kind: "Listing",
data: {}
},
Does this mean that the json is a String when there is no data, but an object otherwise? How can I deserialize with gson properly if this is the case? I've included my classes below. I still need to figure out how to handle the json starting off with an array of basically two different objects (the first listing in the json is describing the link, while the second listing is describing the comments), but I'll cross that bridge when I get there. Thanks in advance if anyone can shed some light on this issue.
Main Class
public static void main(String[] args)
{
ArrayList<CommentsResults> commentsResults = new ArrayList<CommentsResults>();
String commentsURL = "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
URL url = null;
try
{
url = new URL(commentsURL);
} catch (MalformedURLException ex)
{
System.out.println(ex.getMessage());
}
try
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
String jsonText = readAll(bufferedReader);
Gson gson = new GsonBuilder().create();
commentsResults = gson.fromJson(jsonText, new TypeToken<ArrayList<CommentsResults>>(){}.getType());
} catch (IOException ex)
{
System.out.println(ex.getMessage());
}
}
private static String readAll(Reader reader) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
int cp;
while ((cp = reader.read()) != -1)
{
stringBuilder.append((char) cp);
}
return stringBuilder.toString();
}
CommentsResults Class
public class CommentsResults {
private String kind;
private CommentsData data;
public CommentsResults()
{
}
public CommentsResults(String kind, CommentsData data)
{
this.kind = kind;
this.data = data;
}
public String getKind()
{
return kind;
}
public CommentsData getData()
{
return data;
}
public void setKind(String kind)
{
this.kind = kind;
}
public void setData(CommentsData data)
{
this.data = data;
}
}
CommentsData Class
private String modhash;
private List <CommentsChild> children;
public CommentsData()
{
}
public CommentsData(String modhash, List<CommentsChild> children)
{
this.modhash = modhash;
this.children = children;
}
public String getModhash()
{
return modhash;
}
public List<CommentsChild> getChildren()
{
return children;
}
public void setModhash(String modhash)
{
this.modhash = modhash;
}
public void setChildren(List<CommentsChild> children)
{
this.children = children;
}
CommentsChild Class
private String kind;
private Comment data;
public CommentsChild()
{
}
public CommentsChild(String kind, Comment comment)
{
this.kind = kind;
this.data = comment;
}
public String getKind()
{
return kind;
}
public Comment getComment()
{
return data;
}
public void setKind(String kind)
{
this.kind = kind;
}
public void setComment(Comment comment)
{
this.data = comment;
}
Comment Class
public class Comment {
private CommentsResults replies;
private String id;
private int gilded;
private String author;
private String parent_id;
private String body;
private int downs;
private String link_id;
private boolean score_hidden;
private int created_utc;
private String distinguished;
public Comment()
{
}
public Comment(CommentsResults replies, String id, int gilded, String author, String parent_id, String body, int downs, String link_id, boolean score_hidden, int created_utc, String distinguished)
{
this.replies = replies;
this.id = id;
this.gilded = gilded;
this.author = author;
this.parent_id = parent_id;
this.body = body;
this.downs = downs;
this.link_id = link_id;
this.score_hidden = score_hidden;
this.created_utc = created_utc;
this.distinguished = distinguished;
}
public CommentsResults getReplies()
{
return replies;
}
public String getId()
{
return id;
}
public int getGilded()
{
return gilded;
}
public String getAuthor()
{
return author;
}
public String getParent_id()
{
return parent_id;
}
public String getBody()
{
return body;
}
public int getDowns()
{
return downs;
}
public String getLink_id()
{
return link_id;
}
public boolean isScore_hidden()
{
return score_hidden;
}
public int getCreated_utc()
{
return created_utc;
}
public String getDistinguished()
{
return distinguished;
}
public void setReplies(CommentsResults replies)
{
this.replies = replies;
}
public void setId(String id)
{
this.id = id;
}
public void setGilded(int gilded)
{
this.gilded = gilded;
}
public void setAuthor(String author)
{
this.author = author;
}
public void setParent_id(String parent_id)
{
this.parent_id = parent_id;
}
public void setBody(String body)
{
this.body = body;
}
public void setDowns(int downs)
{
this.downs = downs;
}
public void setLink_id(String link_id)
{
this.link_id = link_id;
}
public void setScore_hidden(boolean score_hidden)
{
this.score_hidden = score_hidden;
}
public void setCreated_utc(int created_utc)
{
this.created_utc = created_utc;
}
public void setDistinguished(String distinguished)
{
this.distinguished = distinguished;
}
}
So in the off chance this helps somebody (which seems dubious at this point) I decided to parse the Json manually using recursion. Here's how I did it:
public static void getCommentsOnLink()
{
String commentsURL= "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
URL url = null;
try
{
url = new URL(commentsURL);
} catch (MalformedURLException ex)
{
System.out.println(ex.getMessage());
}
String JsonText = readCommentJsonFromURL(url);
RedditCommentResults redditCommentResults = getCommentResults(JsonText);
}
private static String readCommentJsonFromURL(URL url)
{
String JSONText = null;
try
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
JSONText = readAll(bufferedReader);
} catch (IOException ex)
{
System.out.println(ex.getMessage());
}
return JSONText;
}
private static String readAll(Reader reader) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
int cp;
while ((cp = reader.read()) != -1)
{
stringBuilder.append((char) cp);
}
return stringBuilder.toString();
}
private static RedditCommentResults getCommentResults(String JsonText)
{
JsonParser parser = new JsonParser();
JsonArray completeJson = (JsonArray) parser.parse(JsonText);
//get link and comment object from the array containing an object for each
JsonObject linkParentJson = (JsonObject) completeJson.get(0);
JsonObject commentParentJson = (JsonObject) completeJson.get(1);
//use automatic deserializer for redditLink
JsonObject linkListingDataJson = linkParentJson.getAsJsonObject("data");
JsonObject linkChildrenJson = linkListingDataJson.getAsJsonArray("children").get(0).getAsJsonObject();
JsonObject linkDataJson = linkChildrenJson.getAsJsonObject("data");
Link commentLink = gson.fromJson(linkDataJson, Link.class);
RedditLink redditCommentLink = new RedditLink(commentLink);
//parse comments manually
JsonObject commentDataJson = commentParentJson.getAsJsonObject("data");
JsonArray commentChildrenJson = commentDataJson.getAsJsonArray("children");
//get all of the comments from the JsonArray
ArrayList<RedditComment> redditComments = getNestedComments(commentChildrenJson);
RedditCommentResults redditCommentResults = new RedditCommentResults(redditComments, redditCommentLink);
return redditCommentResults;
}
private static ArrayList<RedditComment> getNestedComments(JsonArray commentWrapperJsonArray)
{
ArrayList<RedditComment> redditComments = new ArrayList();
for (JsonElement commentWrapperJson : commentWrapperJsonArray)
{
//cast Element to Object so we can search for the primitive "kind". Finally we get it as a String
String kind = commentWrapperJson.getAsJsonObject().getAsJsonPrimitive("kind").getAsString();
//if the comment is of type t1 meaning it is a comment and not a "more" (a "more" is a comment which
//hasn't been loaded yet because it does not have a great deal of upvotes relative to other comments)
if (kind.equals("t1"))
{
JsonObject commentJson = commentWrapperJson.getAsJsonObject().getAsJsonObject("data");
Comment comment = gson.fromJson(commentJson, Comment.class);
RedditComment redditComment = new RedditComment(comment);
JsonElement repliesJson = commentJson.get("replies");
//if the reply is not equal to an empty String (i.e. if there is at least one reply)
if (!repliesJson.isJsonPrimitive())
{
JsonObject dataJson = repliesJson.getAsJsonObject().getAsJsonObject("data");
JsonArray childrenJson = dataJson.getAsJsonArray("children");
ArrayList<RedditComment> nestedComments = getNestedComments(childrenJson);
redditComment.setReplies(nestedComments);
}
redditComments.add(redditComment);
}
}
return redditComments;
}
You have to remove the private CommentsResults replies; from Comment Class and compose replies in CommentsChild class. According to Json fomate you model is
CommentResult -
CommentsData --
List <CommentsChild> children---
CommentsResults replies
recursion/ repeation of comment result
public class CommentsChild {
private String kind;
private Comment data;
//
private CommentsResults replies;
}