Spring Data neo4j - Id generation strategies - java

I'm working on an example project in which I have a model class Movie and I want this movie to have a UUID as the identifier.
I tried the following code.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.hibernate.annotations.GenericGenerator;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import org.springframework.data.annotation.Id;
import javax.persistence.GeneratedValue;
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
#NodeEntity
public class Movie {
#Id #GeneratedValue(generator = "uuid")
#GenericGenerator(name="uuid", strategy="uuid2")
private String id;
private String title;
private int released;
private String tagline;
#Relationship(type = "ACTED_IN", direction = Relationship.INCOMING)
private List<Role> roles = new ArrayList<>();
public Movie() {
}
public Movie(String title, int released, String tagline) {
this.title = title;
this.released = released;
this.tagline = tagline;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public int getReleased() {
return released;
}
public String getTagline() {
return tagline;
}
public Collection<Role> getRoles() {
return roles;
}
public void addRole(Role role) {
this.roles.add(role);
}
}
This code is generating an error.
org.neo4j.ogm.exception.MappingException: No identity field found for class: movies.spring.data.neo4j.domain.Movie
here is the reference I used to write this code
I am using neo4j-ogm-core:2.1.3
I didn't understand what was in the reference fully.
but I needed to import Hibernate to use #GenericGenerator
Question:
How can I use UUID inside my model. knowing that I'm using Spring Data?
Note: I am new to Neo4j and Spring. I am having difficulties asking the proper questions.

Alternatively, you can use the GraphAware Neo4j UUID. According the library REDME file:
GraphAware UUID is a simple library that transparently assigns a UUID
to newly created nodes and relationships in the graph and makes sure
nobody can (accidentally or intentionally) change or delete them.
Simply download GraphAware Neo4j Framework and GraphAware Neo4j UUID .jar files to /plugins directory, modify few lines in neo4j.conf file and restart Neo4j. After it, UUIDs will be assigned to each node / relationships created in the Neo4j graph.
This approach does not depends on Spring.

Related

How to make the connection between the mysql database and springboot application

I have made a table persons in a schema name test_schema. I have connected the database from DATABASE > CONNECT TO DATABASE in mysql workbench. Then I tried to connect with that but that doesn't seem to work somehow.
BTW I have cloned it from github and trying to run my database in here.
I have tried to see the status but that shows running but the data is not fetching from the database.
application.yml
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/persons
username: root
password: users
jpa:
hibernate.ddl-auto: null
generate-ddl: true
show-sql: true```
UsersRepository.java
package com.techprimers.db.repository;
import com.techprimers.db.model.Users;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UsersRepository extends JpaRepository<Users, Integer> {
}
Users.java
package com.techprimers.db.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Users {
#Id
#GeneratedValue
#Column(name = "id")
private Integer id;
#Column(name = "token")
private String token;
#Column(name = "name")
private String name;
#Column(name = "post")
private Integer post;
public Users() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPost() {
return post;
}
public void setPost(Integer post) {
this.post = post;
}
}
UsersResources.java
package com.techprimers.db.resource;
import com.techprimers.db.model.Users;
import com.techprimers.db.repository.UsersRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping(value = "/rest/users")
public class UsersResource {
#Autowired
UsersRepository usersRepository;
#GetMapping(value = "/all")
public List<Users> getAll() {
return usersRepository.findAll();
}
}
SpringBootMysqldbApplication.java
package com.techprimers.db;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#EnableJpaRepositories(basePackages = "com.techprimers.db.repository")
#SpringBootApplication
public class SpringBootMysqldbApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMysqldbApplication.class, args);
}
}
The result should have been the table elements but instead the Whitelabel Error Page is showing. I don't know what I have been doing wrong since there is nothing much to do. I just modified the code according to my needs but I think I somehow messed with the database connection or I am doing the database connection wrong.
Thanks in advance.
I have come to notice that you said TABLE NAME IS "PERSONS", but in url you have mentioned that as DB name
jdbc:mysql://${DB_SERVER_NAME}:${DB_PORT}/${DB_DATABASE}:currentSchema=${DB_SCHEMA};
which is jdbc:mysql://localhost:3306/<db-name>
Check that once
Unfortunately I can't comment yet but I think your database enforces ssl by default Since MySQL 5.7.5, but it is not obligatory for clients by default. Check this url please jdbc:mysql://localhost:3306/persons?useSSL=false
As Avi mentioned, If your database is test_schema write it in the url instead of persons
And please, provide errors and exceptions right in the question if there any
Link how to handle ssl in mysql
Stackoverflow spring and mysql ssl question

save working but persist not working in hibernate 4.1.1

I am trying to save data usign hsqldb and I am using hibernate 4.1.4.Final. My problem is I want to save data using persist but when I tried to do it's showing following error:
org.hibernate.PersistentObjectException: detached entity passed to persist: main.java.entity.Advocate
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:835)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:828)
at org.hibernate.engine.spi.CascadingAction$7.cascade(CascadingAction.java:315)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:844)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:819)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:823)
at main.java.service.LegalService.registerCase(LegalService.java:46)
at main.java.tester.Tester.registerCase(Tester.java:52)
at main.java.tester.Tester.main(Tester.java:28)
But when I use save method it worked.So I want to know how persist and save makes difference? and my entity classes are serialized.How to solve this persist error.
Here is my class
package main.java.service;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import main.java.businessTier.CaseTO;
import main.java.entity.Advocate;
import main.java.entity.Case;
public class LegalService {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()). buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
public int registerCase(CaseTO caseTO) {
try
{
Session session;
session=sessionFactory.openSession();
session.beginTransaction();
Case c = new Case();
Advocate a = new Advocate();
a.setAdvocateId(caseTO.getAdvocateId());
c.setAdvocate(a);
c.setClientAge(caseTO.getClientAge());
c.setClientName(caseTO.getClientName());
c.setDate(caseTO.getDate());
c.setDescription(caseTO.getDescription());
session.persist(c);
session.getTransaction().commit();
return c.getCaseNo();
}
catch(Exception e){
e.printStackTrace();
return 0;
}
}
}
Here are my entity class
Advocate.java
package main.java.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#Table(name="Db_Advocate")
#DynamicInsert(value=true)
#DynamicUpdate(value=true)
public class Advocate {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="advocateId")
private Integer advocateId;
#Column(name="name")
private String name;
#Column(name="age")
private Integer age;
#Column(name="category")
private String category;
#Column(name="court")
private String court;
#Column(name="city")
private String city;
public Integer getAdvocateId() {
return advocateId;
}
public void setAdvocateId(Integer advocateId) {
this.advocateId = advocateId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getCourt() {
return court;
}
public void setCourt(String court) {
this.court = court;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Case.java
package main.java.entity;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#Table(name="DB_CASE")
#DynamicInsert(value=true)
#DynamicUpdate(value=true)
public class Case {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer caseNo;
#JoinColumn(name="advocateId")
#ManyToOne(cascade=CascadeType.ALL)
private Advocate advocate;
private String clientName;
private Integer clientAge;
private String description;
private Date date;
public Integer getCaseNo() {
return caseNo;
}
#Column(name="caseNo")
public void setCaseNo(Integer caseNo) {
this.caseNo = caseNo;
}
public Advocate getAdvocate() {
return advocate;
}
public void setAdvocate(Advocate advocateId) {
this.advocate = advocateId;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public Integer getClientAge() {
return clientAge;
}
public void setClientAge(Integer clientAge) {
this.clientAge = clientAge;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate() {
return date;
}
#Column(name="data",nullable=true)
public void setDate(Date date) {
this.date = date;
}
}
First you need to understand behaviour of persist().
Below are the links that will help you understand the behaviour
Whats the difference between persist() and save() in Hibernate?
http://javarevisited.blogspot.in/2012/09/difference-hibernate-save-vs-persist-and-saveOrUpdate.html
Now in order to solve this problem in your code .. use merge() instead of persist().
Why persist() gave the exception
persist() does not work for detached objects .You need to know how hibernate determines whether an object is detached or not.
UPDATE
Why the identifier generation strategy auto solved your problem
As i mentioned above that you need to understand the rules by which hibernate identifies whether an object is detached or transient. Below are the rule
If the the entity has a null value for identifier or the version attribute is null it is considered as transient other wise detached.
If you use auto-generated identifiers, and the identifier is not null, then Hibernate considers it as a detached entity.
If you are using assigned identifier strategy then hibernate will issue a fetch to determine whether the identifier exists in db based on that your entity will be either transient or detached.
Now that being said .. we analyse your code.
In your code you have Advocate entity whose identifier strategy is IDENTITY.In the below code
Case c = new Case();
Advocate a = new Advocate();
a.setAdvocateId(caseTO.getAdvocateId());
You are setting the identifier property of Advocate instance manually.At the time of flush when transaction commits ,hibernate will see that the identifier generation strategy is IDENTITY and the identifier value is set in the advocate instance hence it will conclude that the entity instance is detached (this is from the rule 1 described above).And hence the persist() method gave exception for the advocate instance as it is deemed to be detached from hibernate.
From rule 2 we can say that your code will not work just by changing the generation strategy to auto.You might have done some other changes.
I have tried your code on my system it is giving the same exception even if i change the generation strategy to auto which is in consistent with the rules
You might be doing something different in your code .. please check and update.
Please also post the identifier that you are setting in the advocate and the actual identifier generated for that advocate in database with auto generation strategy, that might be helpful
Please Add below code at id
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Then persist will work

Simple CRUD tutorial about Play Framework and MySQL using Ebean?

I am new to Play Framework. I have started learning it and so far I am enjoying it.
I have started to learn Play Java.
I have my controller and model set up as follow:
Controller:
package controllers;
import play.mvc.Controller;
import play.mvc.Result;
//Import Product model
import models.Product;
public class Products extends Controller{
/**
* List all Products
*/
public static Result list(){
Object allProducts = Product.findAll();
return ok((Content) allProducts); //return all products
}
}
Model:
package models;
import java.util.List;
import play.db.*;
import play.api.db.DB;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Query;
public class Product {
public int id;
public String name;
public String description;
public Product(){
}
public Product(int id, String name, String description){
this.id = id;
this.name = name;
this.description = description;
}
public static String findAll(){
//Using ebean and MySql, fech the product table
//and return all products
}
}
To enable the use of MySql, I have already edited the /conf/application.conf as follow:
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost/play_db?characterEncoding=UTF-8"
db.default.user=user
db.default.password=pass
ebean.default="models.*"
I have a play_db database with one table shown as follow:
My problem is how to fetch all the products in the Product model using ebean and MySQL.
Can someone please point me to a simple crud tutorial which uses play java in combination with ebean and MySql? Thanks
Anyone?
NOTE
By the way, I am using Play v.2.3.5 for Java
Hooray!!!
List action
public static Result list(){
List<Product> products = Product.findAll();
return ok(play.libs.Json.toJson(products));
}
findAll method in Product Model
public static List<Product> findAll(){
return Product.find.orderBy("id").findList();
}
Lastly, I have to enable evolution in /conf/application.conf by uncommenting the following line
# evolutionplugin=disabled
Add #Entity just before public class Product extends Model{
Final code:
package models;
import java.util.List;
import javax.persistence.Entity;
import play.db.*;
import play.db.ebean.Model;
import play.api.db.DB;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Query;
#Entity
public class Product extends Model{
public int id;
public String name;
public String description;
public static Model.Finder<String, Product> find = new Model.Finder<String, Product>(String.class, Product.class);
public Product(){
}
public Product(int id, String name, String description){
this.id = id;
this.name = name;
this.description = description;
}
public static List<Product> findAll(){
return Product.find.orderBy("id").findList();
}
}
I hope this will help anyone who is also new to Play Java

How to avoid LazyInitializationException in Hibernate?

I am using Hibernate as the ORM for a database that has a number of foreign key relationships. The problem is that sometimes I want to fetch these related datasets and sometimes I do not, so on these collections I have set "fetch" to "lazy". Unfortunately, every time I try to serialize these objects Hibernate will throw a LazyInitializationException, because the session is closed. Using an OpenSessionInView filter simply causes Hibernate to populate these collections anyway, thus defeating the whole purpose of having a lazy collection in the first place.
Is there a simple way to serialize or otherwise extract the data populated in the POJO without triggering the LIE, and without having to populate all of the lazy collections?
EDIT: Here is some example code I am trying to get working, dealing with two tables, "Departments" and "Employees," which is the child in a one-to-many relationship with Departments. I want to be able to view the Departments listed in the database, without having to load all of the Employees that belong to said Departments:
Departments:
package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* Departments generated by hbm2java
*/
#Entity
#Table(name="Departments"
,catalog="test"
)
public class Departments implements java.io.Serializable {
private Integer id;
private String name;
private Set<Employees> employeeses = new HashSet(0);
public Departments() {
}
public Departments(String name) {
this.name = name;
}
public Departments(String name, Set employeeses) {
this.name = name;
this.employeeses = employeeses;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name="Name", nullable=false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch=FetchType.LAZY, mappedBy="departments")
public Set<Employees> getEmployeeses() {
return this.employeeses;
}
public void setEmployeeses(Set employeeses) {
this.employeeses = employeeses;
}
}
Employees:
package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* Employees generated by hbm2java
*/
#Entity
#Table(name="Employees"
,catalog="test"
)
public class Employees implements java.io.Serializable {
private Integer id;
private Departments departments;
private String firstName;
private String lastName;
public Employees() {
}
public Employees(Departments departments, String firstName, String lastName) {
this.departments = departments;
this.firstName = firstName;
this.lastName = lastName;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="DepartmentsId", nullable=false)
public Departments getDepartments() {
return this.departments;
}
public void setDepartments(Departments departments) {
this.departments = departments;
}
#Column(name="FirstName", nullable=false)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="LastName", nullable=false)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
My action class (which gets serialized by the Struts2 XSLT result):
package com.test.view;
import java.util.List;
import java.util.Iterator;
import com.opensymphony.xwork2.ActionSupport;
import com.test.controller.DepartmentsManager;
import com.test.model.Departments;
import com.test.util.HibernateUtil;
public class DepartmentsAction extends ActionSupport {
private DepartmentsManager departmentsManager;
private List<Departments> departmentsList;
public DepartmentsAction() {
this.departmentsManager = new DepartmentsManager();
}
public String list() {
this.departmentsList = departmentsManager.list();
System.out.println("Execute called");
HibernateUtil.createDTO(departmentsList);
return SUCCESS;
}
public List<Departments> getDepartmentsList() {
return departmentsList;
}
public void setDepartmentsList(List<Departments> departmentsList) {
this.departmentsList = departmentsList;
}
}
My Manager class (which the Action class calls to populate the list of Departments):
package com.test.controller;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import com.test.model.Departments;
import com.test.util.HibernateUtil;
public class DepartmentsManager {
public List<Departments> list() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Departments> set = null;
try {
Query q = session.createQuery("FROM Departments");
/*Query q = session.createQuery("FROM Departments d JOIN FETCH d.employeeses e");*/
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
set = (List<Departments>) q.list();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
session.getTransaction().commit();
return set;
}
}
Lazy collections work only within the scope of the transaction (where the owning entity was retrieved from a DB). In other words, you should not pass a Hibernate entity with non-loaded lazy sub-entities or collections outside the transaction scope.
You need either to build another entity or use lazy="false" if you want to pass an entity to JSP, or serialization code or anything else.
Two simple ways to manage lazy loading within view :
Using a Transaction view (consisting in wrapping view calls into JTA transaction (application-managed for instance)
Using an extented persistence context in your bean and flushing it explicitely when you've done with it, that means as soon as you were able to load your lazy objects.
For more information, check this post and the answer that belongs to it:
JPA lazy loading Collections in JSF view - better way than using Filters?

GWT with JDO problem

I just start playing with GWT I'm having a really hard time to make GWT + JAVA + JDO + Google AppEngine working with DataStore.
I was trying to follow different tutorial but had no luck. For example I wend to these tutorials: TUT1 TUT2
I was not able to figure out how and what i need to do in order to make this work.
Please look at my simple code and tell me what do i need to do so i can persist it to the datastore:
1. ADDRESS ENTITY
package com.example.rpccalls.client;
import java.io.Serializable;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
public class Address implements Serializable{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private int addressID;
#Persistent private String address1;
#Persistent private String address2;
#Persistent private String city;
#Persistent private String state;
#Persistent private String zip;
public Address(){}
public Address(String a1, String a2, String city, String state, String zip){
this.address1 = a1;
this.address2 = a2;
this.city = city;
this.state = state;
this.zip = zip;
}
/* Setters and Getters */
}
2. PERSON ENTITY
package com.example.rpccalls.client;
import java.io.Serializable;
import java.util.ArrayList;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
#PersistenceCapable
public class Person implements Serializable{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent private String name;
#Persistent private int age;
#Persistent private char gender;
#Persistent ArrayList<Address> addresses;
public Person(){}
public Person(String name, int age, char gender){
this.name = name;
this.age = age;
this.gender = gender;
}
/* Getters and Setters */
}
3. RPCCalls
package com.example.rpccalls.client;
import java.util.ArrayList;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
public class RPCCalls implements EntryPoint {
private static final String SERVER_ERROR = "An error occurred while attempting to contact the server. Please check your network connection and try again.";
private final RPCCallsServiceAsync rpccallService = GWT.create(RPCCallsService.class);
TextBox nameTxt = new TextBox();
Button btnSave = getBtnSave();
public void onModuleLoad() {
RootPanel.get("inputName").add(nameTxt);
RootPanel.get("btnSave").add(btnSave);
}
private Button getBtnSave(){
Button btnSave = new Button("SAVE");
btnSave.addClickHandler(
new ClickHandler(){
public void onClick(ClickEvent event){
saveData2DB(nameTxt.getText());
}
}
);
return btnSave;
}
void saveData2DB(String name){
AsyncCallback<String> callback = new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
Window.alert("WOOOHOOO, ERROR: " + SERVER_ERROR);
// TODO: Do something with errors.
}
public void onSuccess(String result) {
Window.alert("Server is saying: ' " + result + "'");
}
};
ArrayList<Address> aa = new ArrayList<Address>();
aa.add(new Address("123 sasdf","", "Some City", "AZ", "93923-2321"));
aa.add(new Address("23432 asdf", "Appt 34", "Another City", "AZ", "43434-4432"));
Person p = new Person();
p.setName(name);
p.setAge(23);
p.setGender('m');
p.setAddresses(aa);
// !!!!!!!!!!!!!!!!!! SERVER CALL !!!!!!!!!!!!!!!!!!
rpccallService.saveName(p, callback);
// !!!!!!!!!!!!!!!!!! SERVER CALL !!!!!!!!!!!!!!!!!!
}
}
4. RPCCallsService
package com.example.rpccalls.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
#RemoteServiceRelativePath("calls")
public interface RPCCallsService extends RemoteService {
String saveName(Person p);
}
5. RPCCallsServiceAsync
package com.example.rpccalls.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface RPCCallsServiceAsync {
void saveName(Person p, AsyncCallback<String> callback);
}
6. **RPCCalls.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module rename-to='rpccalls'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<entry-point class='com.example.rpccalls.client.RPCCalls'/>
</module>
I tried to add Key class and everything else in those tutorials but it looks like i'm missing something.
Here is my error:
alt text http://vasura.s3.amazonaws.com/Picture2.png
or before i was getting this error:
Key cannot be resolved to a type
What is the best solution to make this working?
Sriram Narayan says to String-encode the Key to get it to pass through GWT's RPC mechanism:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class SomeDomainClass implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
String id;
The second tutorial you've referenced has a section on shadowing the com.google.appengine.api.datastore.Key class, since it's not available to GWT:
Since I'm not doing anything with the Key class on the client I'm going to stub it out. This actually requires a few steps and involves the super-src feature of GWT XML module files.
You might want to take a look at the GWT documentation, which states that
The heart of GWT is a compiler that converts Java source into JavaScript
, therefore you need to have the source code available to use a given class in the client code.
Once you're fed up with JDO, take a look at objectify. I've found it to be a lot nicer to work with, and it has full GWT interop without DTOs.
You can use the Key class in GWT code by adding these additional jar files:
http://www.resmarksystems.com/code/
appengine-utils-client-1.0.jar
appengine-utils-server-1.0.jar
This basically gives the GWT compiler a GWT-friendly version of the Key and other AppEngine classes. (like Text, Blob and User..)
To use:
Add the appengine-utils-client-1.0.jar anywhere in your build path.
Put the appengine-utils-server-1.0.jar in your WEB-INF/lib folder.
Add the following to your GWT module:
< inherits name="com.resmarksystems.AppEngineDataTypes"/>
Another option would be to implement a DTO ( Data Transfer Object ) that you are using in the client instead of using the persistent objects directly.
Or, you could go to JPA instead of JDO. In the example data class in the appengine JPA docs the Id is a Long instead of that Key implementation http://code.google.com/appengine/docs/java/datastore/usingjpa.html
Could it be that you forgot to create the implementation for the RPCCallsService? I can't see it from the list of files that you have.
You should have a file called RPCCallsServiceImpl.java in RPCCalls/src/com/example/rpccalls/server/, it is the implementation file for the interface RPCCallsService.java.
It will look something like this:
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.example.rpccalls.client.RPCCallsService;
public class RPCCallsServiceImpl extends RemoteServiceServlet implements RPCCallsService {
// Factory to get persistence manager object later
private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactional-optional");
public String saveName(Person p) {
// Data Store need persistence manager object for writing to it
PersistenceManager pm = PMF.getPersistenceManager();
// Recommended way to save an object to the data store
try {
pm.makePersistent(p);
} finally {
pm.close();
}
// You want it to return string
return p.getName();
}
}
Hopefully this help you to solve the problem. Cheers :)

Categories