GWT with JDO problem - java

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 :)

Related

ReactiveCosmosRepository delete functions not working

I'm building a Spring Boot app using CosmosDB as my database. All functions work (creating an item, updating one, get all, get by id,...), apart from delete functions. They don't do anything and since their output is void, it doesn't give me any logs either.
The DAO class:
package projects.trashcanapplication.trashcan.dao;
import com.azure.spring.data.cosmos.core.mapping.Container;
import com.azure.spring.data.cosmos.core.mapping.GeneratedValue;
import com.azure.spring.data.cosmos.core.mapping.PartitionKey;
import org.springframework.data.annotation.Id;
import projects.trashcanapplication.trashcan.models.Address;
import projects.trashcanapplication.trashcan.models.FillStatus;
#Container(containerName = "trashcanData")
public class TrashcanDao{
#GeneratedValue
private String attachments;
private FillStatus fillStatus;
#GeneratedValue
private String rid;
private Address address;
#Id
#PartitionKey
#GeneratedValue
private String id;
#GeneratedValue
private String self;
#GeneratedValue
private String etag;
#GeneratedValue
private int ts;
public TrashcanDao(Address address, FillStatus fillStatus) {
this.fillStatus = fillStatus;
this.address = address;
}
public String getAttachments(){
return attachments;
}
public FillStatus getFillStatus(){
return fillStatus;
}
public String getRid(){
return rid;
}
public Address getAddress(){
return address;
}
public String getId(){
return id;
}
public String getSelf(){
return self;
}
public String getEtag(){
return etag;
}
public int getTs(){
return ts;
}
}
The repository
package projects.trashcanapplication.trashcan.repositories;
import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
public interface TrashcanRepository extends ReactiveCosmosRepository<TrashcanDao, String> {
}
The service calling the repository
package projects.trashcanapplication.trashcan.services;
import com.azure.cosmos.models.PartitionKey;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
import projects.trashcanapplication.trashcan.models.Trashcan;
import projects.trashcanapplication.trashcan.repositories.TrashcanRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#Slf4j
#Service
#AllArgsConstructor
public class TrashcanServiceImpl implements TrashcanService {
private final TrashcanRepository trashcanRepository;
private final TrashcanMapper trashcanMapper;
public Flux<Trashcan> getAllTrashcans() {
return trashcanRepository.findAll().map(trashcanMapper::fromDaoToTrashcan);
}
public Mono<Trashcan> getTrashcanById(String id) {
return trashcanRepository.findById(id).map(trashcanMapper::fromDaoToTrashcan);
}
public String createTrashcan(Trashcan trashcan) {
TrashcanDao saveTrashcan = trashcanMapper.fromTrashcanToDao(trashcan);
trashcanRepository.save(saveTrashcan).subscribe();
return saveTrashcan.getId();
}
public void deleteTrashcan(String id) {
trashcanRepository.deleteById(id, new PartitionKey(id));
log.info(String.format("Deleted trashcan %s", id));
}
}
I have a dataloader temporarily set up to populate my DB with an item upon running the app. The deleteAll() function doesn't work here either.
package projects.trashcanapplication.trashcan.services;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
import projects.trashcanapplication.trashcan.models.Address;
import projects.trashcanapplication.trashcan.models.FillStatus;
import projects.trashcanapplication.trashcan.repositories.TrashcanRepository;
import javax.annotation.PostConstruct;
#Slf4j
#Component
#AllArgsConstructor
public class DataLoader {
private final TrashcanRepository trashcanRepository;
#PostConstruct
void loadData() {
Address address1 = new Address("Begijnendijk", "3130", "Liersesteenweg", "181");
trashcanRepository.deleteAll();
trashcanRepository.save(new TrashcanDao(address1, FillStatus.EMPTY))
.flatMap(trashcanRepository::save)
.thenMany(trashcanRepository.findAll())
.subscribe(trashcan -> log.info(trashcan.getId().toString()))
;
}
}
You're not subscribing anywhere, so the reactive stream isn't executed.
You could solve that by subscribing manually:
trashcanRepository.deleteAll().subscribe()
However, this is not a good practice, and certainly not in your DataLoader as you can't guarantee the order in which the save/delete-logic is executed (maybe the TrashcanDao is saved before you delete everything).
To solve this, you should create a proper reactive stream:
trashcanRepository
.deleteAll()
.then(trashcanRepository.save(new TrashcanDao(address1, FillStatus.EMPTY)))
.thenMany(trashcanRepository.findAll())
// Your previous subscribe() shouldn't compile since it should contain List<TrashcanDao>
.subscribe(trashcans -> log.info(trashcans.size()));

Dao is null but only in one case

Still fairly new to Spring (and StackOverflow) so please forgive me if there's an obvious answer here.
Program I'm working on has 3 model classes: Star, Location, Observation. I've got the first two wired up to MySQL and working just fine. I'm testing each one before moving on so the third isn't yet and is using an ArrayList to store the Observations for the time being. However an Observation needs to retrieve info from the Location. But when I try to get that data out through the LocationDao, it keeps returning NULL. However, in one of my controllers where I need to access the Location data to display it, it works just fine. I'm not seeing a difference between the two.
Relevant code:
Location Model Class
package StarCatalog.models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#Entity
public class Location {
#Id
#GeneratedValue
private int locationId;
#NotNull
#Size(min=3, max=25, message="Name out of bounds")
private String locationName;
#NotNull(message = "Cannot be blank")
private Double latitude;
#NotNull(message = "Cannot be blank")
private Double longitude;
// Constructors
public Location() { }
public Location(String aLocation, Double aLatitude, Double aLongitude) {
locationName = aLocation;
latitude = aLatitude;
longitude = aLongitude;
}
// Getters & Setters
public int getLocationId() {
return locationId;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String location) {
this.locationName = location;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
}
Location Dao
package StarCatalog.models.data;
import StarCatalog.models.Location;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
#Repository
#Transactional
public interface LocationDao extends CrudRepository<Location, Integer> {
}
Observation Model Class
package StarCatalog.models;
import StarCatalog.models.data.LocationDao;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.constraints.NotNull;
public class Observation {
#Autowired
private LocationDao locationDao;
// Primary Key
private int observationId;
private static int nextId = 0;
// Altitude
#NotNull
private Double altitude;
// Azimuth
#NotNull
private Double azimuth;
// ST
#NotNull
private int siderealTimeH;
#NotNull
private int siderealTimeM;
private Double siderealTimeDeg;
// Lat
private Double latitude;
// RA
private Double rightAscension;
// Dec
private Double declination;
// Foreign key of Location
#NotNull
private int locationId;
// Foreign key of Star
#NotNull
private Integer objectId;
// Constructor
public Observation() {
observationId = nextId;
nextId = nextId + 1;
}
// Calculators
public void setLatitude() {
latitude = locationDao.findOne(locationId).getLatitude(); // Error here - locationDao = null
}
// Cut non-applicable code
StarController (Where it works)
package StarCatalog.controllers;
import StarCatalog.models.*;
import StarCatalog.models.data.LocationDao;
import StarCatalog.models.data.StarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.Valid;
import java.util.ArrayList;
#Controller
#RequestMapping("star")
public class StarController {
#Autowired
private StarDao starDao;
#Autowired
private LocationDao locationDao;
// Index
#RequestMapping("")
public String index(Model model) {
Iterable<Star> stars = starDao.findAll();
ArrayList<Observation> observations = ObservationData.getAll();
Iterable<Location> locations = locationDao.findAll(); //This one works just fine.
model.addAttribute("stars", stars);
model.addAttribute("observations", observations);
model.addAttribute("locations", locations);
model.addAttribute("title", "Uranometria 2.0");
return "star/index";
}
I've tried swapping out the findOne in the Observation for findAll just in case that was the problem, but since it's locationDao that's coming back null, it doesn't matter which I use.
If it helps, here's the error it throws:
java.lang.NullPointerException: null
at StarCatalog.models.Observation.setLatitude(Observation.java:58) ~[main/:na]
First of all your whole design is a bit off.
You seem to use a table named Location which maps to a respective
database table and then a class named Observation which seems to be
a super table of the Location table storing data regarding this and
having a reference to the location table.
What you have in place is not a valid table hierarchy desing.
Ideally, the Observation table should be the top level entity,
having a one to many relation with the Location table. You can
check online on how to map this relation very easily.
You do not need an extra ObservationData class just to wrap an
arraylist in there to retrieve the locations. With a one to many
design, your Observation class will containg a list or better yet a
set that will contain the location information for each observation.
The reason why you LocationDao is null in Observation has to do
with the fact, that the class in question is not a Spring managed
bean. Hence Spring does not know how to inject the bean in question
LocationDao. You can get around this, by annotating the Observation
class with #Component which will bring this into Spring context
thus allowing you to do so, but I would recommend against doing this
(see above on how to properly map a relation between them).
LocationDao this is obviously not a DAO, hence the naming
convention is wrong. Also it does not need the #Transactional
annotation.
Avoid injecting beans via field injection and prefer to do this via
constructor.
I hope all the above help.

Spring Data neo4j - Id generation strategies

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.

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

objectify-appengine - Embedded class - not a supported property type

I am trying out the objectify(version 2.2.3) embedded classes example (wiki) on google app engine. I am getting this error:
java.lang.IllegalArgumentException: one: com.mypkg.LevelOne is not a supported property type.
at com.google.appengine.api.datastore.DataTypeUtils.checkSupportedSingleValue(DataTypeUtils.java:184)
The code I have is the same as the one in Wiki. The section in the controller:
EntityWithEmbedded ent = new EntityWithEmbedded();
ent.one = new LevelOne();
ent.one.foo = "Foo Value";
ent.one.two = new LevelTwo();
ent.one.two.bar = "Bar Value";
The EntityWithEmbedded class:
import javax.jdo.annotations.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class EntityWithEmbedded {
#Id public Long id;
#Embedded public LevelOne one;
//getter & setters here
}
Class levelOne:
import javax.persistence.Embedded;
public class LevelOne {
public String foo;
public #Embedded LevelTwo two;
//getter & setters here
}
Class LevelTwo:
public class LevelTwo {
public String bar;
//getter & setters here
}
So it is the basic example that I am trying out. Any ideas on what is missing?
You're using the wrong #Embedded annotation in EntityWithEmbedded.
Use javax.persistence.Embedded rather than javax.jdo.annotations.Embedded

Categories