In my exploration of JPA, I have the code below (which I understand should not be used in production). Running my code produces the following error:
java.lang.IllegalStateException:
Exception Description: Cannot use an EntityTransaction while using JTA.
The Resource code is as follows:
#Path("users")
public class UsersAPI {
#Context
UriInfo uriInfo;
#Inject
UserBean accountsBean;
#GET
#Path("deduplicate")
public Response deduplicateDB(){
List<UserProfile> profiles = accountsBean.getAll();
int profilesNum = profiles.size();
for(int i = 0; i < profilesNum; ++i){
for(int k = 0; k < profilesNum; ++k){
if(i != k){ //if it's not the same profile
if(profiles.get(i).getUsername().equals(profiles.get(k).getUsername())){
accountsBean.remove(profiles.get(k));
profiles.remove(k);
}
}
profilesNum = profiles.size();
}
}
return Response.ok().build();
}
}
The code in the ProfilesBean is as follows:
#Local
#Stateless
public class UserBean {
#PersistenceContext
EntityManager eManager;
public void save(UserProfile data){
eManager.merge(data);
}
public void remove(UserProfile data){
eManager.getTransaction().begin();
eManager.remove(data);
eManager.getTransaction().commit();
}
public List<UserProfile> getAll(){
Query q = eManager.createQuery("SELECT profile FROM Users profile");
return (List<UserProfile>)q.getResultList();
}
}
Here is the code for the Entity class:
#Entity(name="Users")
public class UserProfile {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
Long id;
String password;
#Column(unique=true)
String username;
public UserProfile(String username){
setUsername(username);
}
public UserProfile(){
this(null);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
It seems like the error comes from my misusing the platform somehow. How can I fix this code and not misuse the platform in the future?
If you are using JTA as transaction-type in persistence.xml file just leave JTA handles your transactions
public void remove(UserProfile data){
eManager.remove(eManager.merge(data));
}
UPDATE:
In a more clear solution you could use "find", but you need to provide the object id
public void remove(UserProfile data){
UserProfile e = em.find(UserProfile.class, data.getId());
eManager.remove(e);
}
Related
I want to deserialize into a data structure. Dependent on the version of the JSON data I want to deserialize into different implementations of the same interface. And this works so far with a custom deserializer.
However, in the data structure I use references. And I expect that when undefined references are encountered an exception is thrown. The way I programmed it, this does not work together with the interface.
I created a small example with a (currently not passing) test case to show the desired behavior.
Additional Information:
In the test case, when I use concrete classes (instead of the interface) in readValue the desired behavior occurs. That is, when I write mapper.readValue(buggy, Database2.class); instead of mapper.readValue(buggy, DatabaseI.class);. But then I lose the ability to abstract from the particular content of the JSON data.
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.btc.adt.pop.scen.objectstreams.Person;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.IntNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
public class Example {
#Test
public void test() throws JsonProcessingException {
ObjectMapper mapper =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
SimpleModule module = new SimpleModule();
module.addDeserializer(DatabaseI.class, new ToyDeserializer());
mapper.registerModule(module);
String correct = "{'version':1,'people':[{'id':'a','friends':['b','c']},{'id':'b','friends':['c']},{'id':'c','friends':['b']}]}";
DatabaseI deserCorrect = mapper.readValue(correct, DatabaseI.class);
System.out.println(mapper.writeValueAsString(deserCorrect));
String buggy = "{'version':2,'people':[{'id':'a','friends':['b','c']},{'id':'b','friends':['c']},{'id':'c','friends':['FOO']}]}";
assertThrows(Exception.class, () -> {
mapper.readValue(buggy, DatabaseI.class);
}, "The reference FOO is undefined. An Exception should be thrown.");
}
}
class Person {
#JsonProperty("id")
private String id;
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
#JsonIdentityReference(alwaysAsId = true)
private List<Person> friends = new ArrayList<>();
public Person() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Person> getFriends() {
return friends;
}
public void setFriends(List<Person> friends) {
this.friends = friends;
}
}
interface DatabaseI {
}
class Database1 implements DatabaseI {
private int version;
private List<Person> people = new ArrayList<>();
public Database1() {
}
public List<Person> getPeople() {
return people;
}
public void setPeople(List<Person> people) {
this.people = people;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
class Database2 implements DatabaseI {
private String version;
private List<Person> people = new ArrayList<>();
public Database2() {
}
public List<Person> getPeople() {
return people;
}
public void setPeople(List<Person> people) {
this.people = people;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
class ToyDeserializer extends StdDeserializer<DatabaseI> {
protected ToyDeserializer(Class<?> vc) {
super(vc);
}
public ToyDeserializer() {
this(null);
}
#Override
public DatabaseI deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
JsonNode node = mapper.readTree(jp);
int version = (Integer) ((IntNode) node.get("version")).numberValue();
if (version == 1) {
return mapper.treeToValue(node, Database1.class);
} else {
return mapper.treeToValue(node, Database2.class);
}
}
}
This very good question! If you want to understand why no exception is thrown, your class Person must look like this:
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = Person.class,
resolver = SimpleObjectIdResolverThrowsException.class
)
#JsonIdentityReference
class Person {
String id;
List<Person> friends = new ArrayList<>();
#ConstructorProperties({"id"})
public Person(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Person> getFriends() {
return friends;
}
public void setFriends(List<Person> friends) {
this.friends = friends;
}
}
class SimpleObjectIdResolverThrowsException extends SimpleObjectIdResolver {
public SimpleObjectIdResolverThrowsException() {
super();
}
#Override
public Object resolveId(ObjectIdGenerator.IdKey id) {
if (this._items == null) {
return null;
}
Object obj = this._items.get(id);
if (obj == null) {
throw new RuntimeException("Unresolved reference for: " + id);
}
return obj;
}
#Override
public ObjectIdResolver newForDeserialization(Object context) {
return new SimpleObjectIdResolverThrowsException();
}
}
Now you can set break point in the method resolveId and see what happens when we de-serialize the string "{'version':1,'people':[{'id':'a','friends':['b','c']},{'id':'b','friends':['c']},{'id':'c','friends':['b']}]}":
The problem is that the objects are processed one after the other and the references from the friends list are not resolved at that time.
I want to write a point cut for class instantiation in various packages,like classes inside the subpackages inside com.kepler.xenon (eg.com.kepler.xenon.modules.ticklers.pojo.Tickler,
com.kepler.xenon.modules.product.pojo.Product etc).
//This is my advice
#Aspect
#Component
public class OxAspect {
#After("execution(* com.oxane.xenon..*new(..)) && #within(java.lang.Deprecated)")
public void myAdvice(final JoinPoint jp){
System.out.println(jp.getSignature().getName()+""+jp.getTarget().getClass());
}
}
//This is my class
package com.kepler.xenon.modules.ticklers.pojo;
#Deprecated
public Class Ticklers{
#Id
#TableGenerator(name = "TICKLERS_ID", table = "ID_GENERATOR", pkColumnName = "GEN_KEY", valueColumnName = "GEN_VALUE", pkColumnValue = "TICKLERS_ID", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.TABLE, generator = "TICKLERS_ID")
#Column(name = "TICKLERS_ID", unique = true, nullable = false)
private int ticklersId;
#Column(name = "TASK", nullable = false, length = 256)
private String taskName;
public int getTicklersId() {
return ticklersId;
}
public void setTicklersId(int ticklersId) {
this.ticklersId = ticklersId;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
}
What i want is that if anyone tries to access the class which is deprecated,then pointcut filters that call and triggers advice.
I have done it for methods but i am failing to do it for classes.
I am adding aspect which works for methods,controller and Dao
#Aspect
#Component
public class OxAspect {
private final OxAspectService oxAspectService;
public OxAspect(OxAspectService oxAspectService) {
this.oxAspectService=oxAspectService;
}
#Pointcut("execution(#java.lang.Deprecated * com.oxane.xenon..*(..))"
+ " || execution(* com.oxane.xenon..*.*(..)) && #within(java.lang.Deprecated)")
public void deprecated() {
}
#Before("deprecated()")
public void log(final JoinPoint jp) {
oxAspectService.logDeprecatedMethod(jp);
}
}
Edit:
I have done some research on spring io and found that it can't be done using spring aop. I have to use load time weaving or compile time weaving to achieve what i want. For that i have to use pure aspect j implementation. Correct me if i am wrong.
If I were you I will devide #Pointcut to signle condition like below:
#Pointcut("execution(* com.oxane.xenon..*(..))")
public void anyClassInSubpackage() {
}
#Pointcut("#annotation(java.lang.Deprecated)")
public void deprecatedClass() {
}
#Pointcut("execution(* com.oxane.xenon..*new(..))")
public void anyMethodInSubpackege() {
}
#Pointcut("#within(java.lang.Deprecated)")
public void deprecatedMethod() {
}
#Before("(anyClassInSubpackage() && deprecatedClass()) || (anyMethodInSubpackege() && deprecatedMethod())")
public void myAdvice(final JoinPoint jp){
//TODO
}
I am trying to use spring-data-solr in order to access to my Solr instance through my Spring boot application. I have the following bean class:
#SolrDocument(solrCoreName = "associations")
public class Association implements PlusimpleEntityI {
#Id
#Indexed
private String id;
#Indexed
private String name;
#Indexed
private Point location;
#Indexed
private String description;
#Indexed
private Set<String> tags;
#Indexed
private Set<String> topics;
#Indexed
private Set<String> professionals;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Point getLocation() {
return location;
}
public void setLocation(Point location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<String> getTags() {
return tags;
}
public void setTags(Set<String> tags) {
this.tags = tags;
}
public Set<String> getTopics() {
return topics;
}
public void setTopics(Set<String> topics) {
this.topics = topics;
}
public Set<String> getProfessionals() {
return professionals;
}
public void setProfessionals(Set<String> professionals) {
this.professionals = professionals;
}
}
I have implemented the following repository in order to access to the related information:
public interface AssociationsRepository extends SolrCrudRepository<Association, String> {
}
I have created a configuration class which looks like the following one:
#Configuration
#EnableSolrRepositories(basePackages = {"com.package.repositories"}, multicoreSupport = true)
public class SolrRepositoryConfig {
#Value("${solr.url}")
private String solrHost;
#Bean
public SolrConverter solrConverter() {
MappingSolrConverter solrConverter = new MappingSolrConverter(new SimpleSolrMappingContext());
solrConverter.setCustomConversions(new CustomConversions(null));
return solrConverter;
}
#Bean
public SolrClientFactory solrClientFactory () throws Exception {
return new MulticoreSolrClientFactory(solrClient());
}
#Bean
public SolrClient solrClient() throws Exception {
return new HttpSolrClient.Builder(solrHost).build();
}
#Bean
public SolrOperations associationsTemplate() throws Exception {
SolrTemplate solrTemplate = new SolrTemplate(solrClient());
solrTemplate.setSolrConverter(solrConverter());
return solrTemplate;
}
}
Unfortunately, when I try to read an association from my Solr instance I got the following error:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [org.springframework.data.solr.core.geo.Point]
I don't understand why it is not able to find a converter if I have explicitly defined it in the solrTemplate() method.
This is my POM definition:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
Thank you for your help.
EDIT:
I've also tried with different BUILD-RELEASEs but they are highly unstable and I've found a lot of errors using them.
Alessandro, as you can see directly in the GeoConverters class on GitHub, the implemented converters are only for:
org.springframework.data.geo.Point
and not for:
org.springframework.data.solr.core.geo.Point
Simply use this class and you don't even need a custom converter for this. Spring Data for Solr will perform the conversion for you.
I'm using a slightly patched version of the 3.0.0 M4, but I'm pretty sure this solution should apply seamlessly also to your case.
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.
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