FIQL SearchContext throws NullPointerException when injected with #Context - cxf

I am trying to implement a simple Rest service using FIQL but my code throws NullPointerException at the point where I inject the SearchContext with the #Context. Here is my code
My service class:
import java.util.*;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.jaxrs.ext.search.SearchCondition;
import org.apache.cxf.jaxrs.ext.search.SearchContext;
#Path("/search")
public class Books {
private List<Book> theBooks = new LinkedList<Book>();
#Path("/book")
#GET
#Produces(MediaType.APPLICATION_XML)
public List<Book> getBook(#Context SearchContext searchContext) {
theBooks.add(new Book("1", "nick1"));
theBooks.add(new Book("2", "nick2"));
theBooks.add(new Book("3", "nick3"));
theBooks.add(new Book("4", "nick4"));
theBooks.add(new Book("5", "nick5"));
SearchCondition<Book> condition = searchContext
.getCondition(Book.class);
return condition.findAll(theBooks);
}
}
My Book class
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Book {
private String id;
private String author;
public Book(){ }
public Book(String id, String ownerinfo) {
this.id = id;
this.author = ownerinfo;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOwnerinfo() {
return author;
}
public void setOwnerinfo(String ownerinfo) {
this.author = ownerinfo;
}
}
I am using maven and I have used the dependency
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-search</artifactId>
<version>2.7.5</version>
</dependency>
According to this CXF-4949 my code (I believe) should work but I still the searchContext is null after the #Context
Any ideas?
Thanks

I managed to solve this out. I was missing the declaration of the SearchContextProvider in the beans.xml file. I just added the line
<bean class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/>
in the <jaxrs:providers> tag and now it works fine.
More about FIQL here
Thanks

Related

BaseTest class doesn't initialize the Webdriver instance

I have gone through similar type Q&As, but couldn't figure out the issue in my code.
This is my BaseTest class
`
package com.supportiveTests;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.After;
import io.cucumber.java.Before;
public class BaseTests {
public static WebDriver driver;
#Before
public void setUpDriver() {
System.setProperty("webdriver.chrome.driver", "src/main/resources/Drivers/chromedriver.exe");
driver = new ChromeDriver();
}
#After
public void quitDriver() {
this.driver.quit();
System.out.println("done AfterTest");
}
}
`
This is my stepDefinition class (LoginPageSteps)
`
package com.stepDefinitions;
import com.pageObjects.LoginPage;
import com.supportiveTests.BaseTests;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.testng.annotations.Test;
#Test
public class LoginPageSteps extends BaseTests {
LoginPage obj_login;
#Given("User is on Google Home page")
public void user_is_on_google_home_page() {
BaseTests.driver.navigate().to("https://www.google.com/");
}
#Given("User is navigated to SwagLabs Login page")
public void user_is_navigated_to_swag_labs_login_page() {
BaseTests.driver.navigate().to("https://www.saucedemo.com/");
}
#When("^User enters valid (.*) and (.*)$")
public void user_enters_valid_standard_user_and_secret_sauce(String username, String password) {
obj_login = new LoginPage(driver);
obj_login.enterUserName(username);
obj_login.enterPassword(password);
}
#When("clicks on LOGIN button")
public void clicks_on_login_button() {
obj_login.clickOnLogin();
}
#Then("User is navigated to SwagLAbs Home page")
public void user_is_navigated_to_swag_l_abs_home_page() throws InterruptedException {
BaseTests.driver.getCurrentUrl().contains("https://www.saucedemo.com/inventory.html");
Thread.sleep(2000);
BaseTests.driver.quit();
}
}
`
This is my TestRunner class
`
package com.supportiveTests;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/test/Features",
glue = {"com/stepDefinitions"},
monochrome = true,
plugin = {
"pretty", "html:target/HTMLReports/report.html",
"json:target/JSONReports/report.json",
"junit:target/JUnitReports/report.xml"
}
)
public class TestRunner {
}
`
This is my pageObject class (LoginPage)
`
package com.pageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
By txt_username = By.xpath("//input[#id='user-name']");
By txt_password = By.xpath("//input[#id='password']");
By btn_login = By.xpath("//input[#id='login-button']");
public void enterUserName(String username){
driver.findElement(txt_username).sendKeys(username);
}
public void enterPassword(String password){
driver.findElement(txt_password).sendKeys(password);
}
public void clickOnLogin(){
driver.findElement(btn_login).click();
}
}
When the above TestRunner class is executed, I get this error
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.navigate()" because "com.supportiveTests.BaseTests.driver" is null
at com.stepDefinitions.LoginPageSteps.user_is_on_google_home_page(LoginPageSteps.java:16)
I went through the similar Q&As, where the solutions for driver initialization were provided, but couldn't figure out the issue. I am at basic level of Selenium testing framework, so appreciate any guidance on fixing this.

How to fetch the uploaded file path as response from rest-api call

I have a reactjs page that uploads a file to server. The server is just a spring-boot app that hosts rest api to serve the upload. Once the file is uploaded, i want to return the absolute path of the uploaded file as part of my response. I am able to achieve that as well but the response body shows just ReadableStream when i console logged it. I am not getting the actual path of the file that am setting in spring before sending out the response.
I Have tried to set the response entity object with body containing the response json in string format.
React Code:
import React from 'react';
class UploadImage extends React.Component{
constructor(props){
super(props);
this.state={
uploadData:''
}
this.handleFileUpload=this.handleFileUpload.bind(this);
}
handleFileUpload=(event)=>{
event.preventDefault();
//alert('uploaded file')
//console.log(this.uploadedFile.files[0]);
const data = new FormData();
data.append('uploadedFile',this.uploadedFile.files[0]);
fetch('http://localhost:8080/laptops/upload',{
method:'POST',
body:data
}).then((response) => {
console.log(response);
console.log(response.json);
});
}
render(){
return (
<div>
<form onSubmit={this.handleFileUpload}>
<input type='file' ref={(ref)=>{this.uploadedFile=ref}}/>
<input type='submit' value='upload'/>
</form>
</div>
);
}
}
export default UploadImage;
Boot code: (only look into the post mapping function)
package react.demo.app;
import oracle.jdbc.proxy.annotation.Post;
import org.apache.commons.io.FilenameUtils;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.persistence.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
#Entity
class Laptop{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String brand;
private double price;
private String image;
public Laptop(){
}
public Laptop(String name,String brand,double price,String image){
this.name=name;
this.brand=brand;
this.price=price;
this.image=image;
}
public long 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 getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
#Repository
interface LaptopRepository extends JpaRepository<Laptop,Long>{}
#Service
class LaptopService{
#Autowired
LaptopRepository laptopRepository;
public void addLaptop(Laptop laptop){
laptopRepository.save(laptop);
}
public Laptop getLaptopById(long id){return laptopRepository.getOne(id); }
public List<Laptop> getAllLaptops(){
return laptopRepository.findAll();
}
}
#RestController
#RequestMapping("/laptops")
class LaptopApi{
#Autowired LaptopService laptopService;
private String uploadDir = "C:\\Users\\rajen\\Development\\upload_images\\";
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping(value="/",produces="application/json")
public List<Laptop> getAllLaptops(){
return laptopService.getAllLaptops();
}
#CrossOrigin(origins = "http://localhost:3000")
#PostMapping(value = "/upload")
public ResponseEntity upload(#RequestParam("uploadedFile") MultipartFile uploadedFile) throws IOException {
System.out.println("invoked upload");
File f = new File(uploadDir+uploadedFile.getOriginalFilename());
uploadedFile.transferTo(f);
System.out.println("return uploaded file:"+f.toURI());
HttpHeaders responseHeaders = new HttpHeaders();
return ResponseEntity.ok().headers(responseHeaders).body("{uploadedfile:"+f.getAbsolutePath()+"}");
}
#GetMapping(value="/getLaptopById",produces="application/json")
public Laptop getLaptopById(#RequestParam long id){
System.out.println("laptop by id:"+id);
return laptopService.getLaptopById(id);
}
#PostMapping(value="/addLaptop")
public void addLaptop(#RequestBody Laptop laptop){
laptopService.addLaptop(laptop);
}
}
#SpringBootApplication
public class AppApplication implements CommandLineRunner {
#Autowired LaptopService laptopService;
public static void main(String[] args){
SpringApplication.run(AppApplication.class,args);
}
#Override
public void run(String... args) throws Exception {
Laptop laptop = new Laptop("Dell Inspiron","Dell",new Double(25990),"https://i.pinimg.com/564x/4a/bb/86/4abb8659d4d951a6fefefe401a02aeb7.jpg");
laptopService.addLaptop(laptop);
System.out.println("Laptop Added");
}
}
i expect to see the file path as part of the response body but am getting only Readablestream as the body.
Refer to console log here
Assuming you are receiving a json payload, you need to call the .json() method method on the promise to extract the body data, and return that value (as opposed to just .json, an attempt to access property on the response). Alternatively, if the body data is simply text -- which it may be given the value you are attempting to return, you may need to call the .text() method.
fetch('http://localhost:8080/laptops/upload', {
method:'POST',
body:data
}).then((response) => {
return response.json();
}).then(finalRes => console.log(finalRes))
.catch(e)
}

I want to convert csv file to xml

I want to convert csv file to xml and i want to send the converted xml file to a queue in activemq..Is there any sample code or any reference websites or blogs please help to find sample code for this program..
Use the Bindy and Xstream components. From http://workingwithqueues.blogspot.ch/2012/07/converting-csv-to-xml-with-camel-bindy.html (with a JMS endpoint instead of a file endpoint):
DataFormat bindy = new BindyCsvDataFormat("com.package.dto");
from("file://TEST?fileName=Employee.csv")
.unmarshal(bindy)
.marshal()
.xstream()
.to("jms:queue:FOO.BAR");
For connecting to JMS have a look at the JMS and ActiveMQ components.
package org.mycompany.conversion;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Greeting {
#XmlElementWrapper(name = "Person")
#XmlElement(name = "persons")
private List<Person> persons;
public List<Person> getPerson() {
return persons;
}
public void setPerson(List<Person> persons) {
this.persons = persons;
}
}
========================================================================================
package org.mycompany.conversion;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#CsvRecord(separator = ",")
public class Person {
#DataField(pos = 1)
#XmlElement
private int id;
#DataField(pos = 2)
#XmlElement
private String name;
#DataField(pos = 3)
#XmlElement
private int age;
#Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
======================================================================================
package org.mycompany.conversion;
import javax.xml.bind.JAXBContext;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.converter.jaxb.JaxbDataFormat;
import org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.spi.DataFormat;
public class CsvConversion {
public static void main(String[] args) throws Exception {
JaxbDataFormat xmlDataFormat = new JaxbDataFormat();
JAXBContext con = JAXBContext.newInstance(Greeting.class);
xmlDataFormat.setContext(con);
DataFormat bindy = new BindyCsvDataFormat(Person.class);
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("file:src/main/data/in/csv?noop=true").split().tokenize("\n").unmarshal(bindy)
// constanr(true):-aggregate all using same expression
.aggregate(constant(true), new AttachAggregation())
//mandatory after aggregate
.completionTimeout(100)//end after this gives problem
.marshal(xmlDataFormat).log("xml body is ${body}")
.to("file:src/main/data/in/xml?fileName=convertedXml.xml");// .aggregate(new
// AttachAggreagation());
}
});
context.start();
Thread.sleep(5000);
}
}
=========================================================================================
package org.mycompany.conversion;
import java.util.ArrayList;
import java.util.List;
import org.apache.camel.Exchange;
import org.apache.camel.processor.aggregate.AggregationStrategy;
public class AttachAggregation implements AggregationStrategy {
List<Person> list = new ArrayList();
Greeting gre = new Greeting();
#Override
//person-address
// greeting-user
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
if (oldExchange == null) {
Person newBody1 = newExchange.getIn().getBody(Person.class);
list.add(newBody1);
return newExchange;
} else {
Person newBody2 = newExchange.getIn().getBody(Person.class);
list.add(newBody2);
gre.setPerson(list);
oldExchange.getIn().setBody(gre);
return oldExchange;
}
}
}

Tapestry Hibernate database empty on page reload

I have just recently started learning Tapestry, trying to make my own Celebrity Collector application.
Everything worked fine, until I wanted to provide a database support instead of mocked database.
I'm using Hibernate 3.6 with Tapestry 5.3.7.
I have configured my database like this:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:target\database</property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password">sa</property>
<property name="hbm2ddl.auto">create-drop</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
</session-factory>
</hibernate-configuration>
My DAO interface and implementation looks like this:
package com.example.addressbook.data;
import java.util.List;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.PostInjection;
import com.example.addressbook.entities.Celebrity;
public interface CelebrityDao {
#CommitAfter
int count();
#CommitAfter
void add(Celebrity celebrity);
#CommitAfter
Celebrity get(long id);
#CommitAfter
List<Celebrity> getAll();
#CommitAfter
List<Celebrity> getRange(long startIndex, long endIndex);
#PostInjection
void prepare();
}
package com.example.addressbook.data.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import com.example.addressbook.data.CelebrityDao;
import com.example.addressbook.entities.Celebrity;
public class CelebrityDaoImpl implements CelebrityDao {
#Inject
protected Session session;
public void add(Celebrity celebrity) {
session.persist(celebrity);
}
public Celebrity get(long id) {
Criteria criteria = session.createCriteria(Celebrity.class);
criteria.add(Restrictions.eq("id", id));
Celebrity celebrity = (Celebrity) criteria.uniqueResult();
return celebrity;
}
public List<Celebrity> getAll() {
Criteria criteria = session.createCriteria(Celebrity.class);
List rawResults = criteria.list();
List<Celebrity> results = new ArrayList<Celebrity>();
for (Object object : rawResults) {
results.add((Celebrity) object);
}
return results;
}
public List<Celebrity> getRange(long startIndex, long endIndex) {
Criteria criteria = session.createCriteria(Celebrity.class);
criteria.add(Restrictions.between("id", startIndex, endIndex));
List rawResults = criteria.list();
List<Celebrity> results = new ArrayList<Celebrity>();
for (Object object : rawResults) {
results.add((Celebrity) object);
}
return results;
}
public void prepare() {
// adding some initial records in the database
}
public int count() {
return getAll().size();
}
}
My ShowAll class is here:
package com.example.addressbook.pages;
import java.text.Format;
import java.util.List;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SessionState;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.grid.GridDataSource;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.BeanModelSource;
import com.example.addressbook.data.CelebrityDao;
import com.example.addressbook.entities.Celebrity;
import com.example.addressbook.model.User;
import com.example.addressbook.util.CelebrityEncoder;
import com.example.addressbook.util.CelebritySelectModel;
import com.example.addressbook.util.Formats;
import com.example.addressbook.util.HibernateEntityDataSource;
public class ShowAll {
#SessionState
private User user;
private boolean userExists;
#Inject
private CelebrityDao dao;
#InjectPage
private Details detailsPage;
#Property
private Celebrity celebrity;
#Inject
private BeanModelSource beanModelSource;
#Inject
private Messages messages;
String onActivate() {
if (!userExists)
return "Index";
return null;
}
#OnEvent(component = "detailsLink")
Object onShowDetails(long id) {
Celebrity celebrity = dao.get(id);
detailsPage.setCelebrity(celebrity);
System.err.println("Requested ID: " + id);
System.err.println("Result: " + celebrity.getLastName());
return detailsPage;
}
public BeanModel<Celebrity> getModel() {
return beanModelSource.createDisplayModel(Celebrity.class, messages);
}
public List<Celebrity> getAllCelebrities() {
return this.dao.getAll();
}
public Format getDateFormat() {
return Formats.getDateFormat();
}
public User getUser() {
return user;
}
public GridDataSource getCelebritySource() {
return new HibernateEntityDataSource<Celebrity>(Celebrity.class, dao);
}
public SelectModel getCelebrityModel() {
return new CelebritySelectModel(getAllCelebrities());
}
public ValueEncoder<Celebrity> getCelebrityEncoder() {
return new CelebrityEncoder(dao);
}
#Persist
private Celebrity selectedCelebrity;
public Celebrity getSelectedCelebrity() {
return selectedCelebrity;
}
public void setSelectedCelebrity(Celebrity selectedCelebrity) {
this.selectedCelebrity = selectedCelebrity;
}
public String getSelectedCelebrityName() {
if (selectedCelebrity == null) {
return "";
}
return selectedCelebrity.getFirstName() + " " + selectedCelebrity.getLastName();
}
}
And here is how I add new ones:
package com.example.addressbook.pages;
import org.apache.tapestry5.ioc.annotations.Inject;
import com.example.addressbook.data.CelebrityDao;
import com.example.addressbook.entities.Celebrity;
public class AddCelebrity {
private Celebrity celebrity;
#Inject
private CelebrityDao dao;
public void onActivate() {
System.out.println("OnActivate: " + dao.getAll().toString());
if (celebrity == null) {
celebrity = new Celebrity();
}
}
public Celebrity getCelebrity() {
return celebrity;
}
public void setCelebrity(Celebrity celebrity) {
this.celebrity = celebrity;
}
Object onSuccess() {
dao.add(celebrity);
System.out.println("All celebrities: " + dao.getAll().toString());
return ShowAll.class;
}
}
The problem is the following:
When I first come to ShowAll page, my records are pulled from the database and rendered.
When I refresh the page, the records are removed magically and nothing is displayed. The database is empty (dao.getAll() returns and empty list)
When I add a new Celebrity via AddCelebrity page, it is inserted into the database, but as the page is refreshed, the magic happens again and the database is empty again.
I have binded my DAO interface and implementation in AppModule class:
public static void bind(ServiceBinder binder) {
binder.bind(SupportedLocales.class, SupportedLocalesImpl.class);
binder.bind(CelebrityDao.class, CelebrityDaoImpl.class);
}
HELP!! :)
The answer was to add another method to AppModule class
#Match("*Dao")
public static void adviseTransactions(HibernateTransactionAdvisor advisor,
MethodAdviceReceiver receiver) {
advisor.addTransactionCommitAdvice(receiver);
}
So that Tapestry could actually do something with #CommitAfter annotation on my DAO methods.

JDO + RequestFactory - entity versioning

I was trying to set-up a really trivial RequestFactory example, but I failed. I persist entities in to my datastore just find, however when trying to pull them out again, i get a
com.google.web.bindery.requestfactory.server.UnexpectedException: The persisted entity with id aglub19hcHBfaWRyCgsSBFVzZXIYBAw has a null version
So first of all this is my JPO annotated entity class. At the end you find to static function for RequestFactory to call, and a non-static member function which will become an InstanceRequest.
package com.test.server;
import java.util.List;
import javax.jdo.PersistenceManager;
import javax.jdo.annotations.Column;
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.jdo.annotations.Version;
import javax.jdo.annotations.VersionStrategy;
#PersistenceCapable(identityType = IdentityType.APPLICATION)
#Version(strategy = VersionStrategy.VERSION_NUMBER, column = "VERSION", extensions = { #Extension(vendorName = "datanucleus", key = "field-name", value = "version") })
public class User {
public User() {
}
public User(String name) {
this.name = name;
}
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
#Persistent
#Column(name = "version")
private Integer version;
#Persistent
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static final PersistenceManager persistenceManager() {
return PMF.get().getPersistenceManager();
}
#SuppressWarnings("unchecked")
public static List<User> findAllUsers() {
PersistenceManager pm = persistenceManager();
try {
String query = "SELECT FROM " + User.class.getName();
List<User> objects = (List<User>) pm.newQuery(query).execute();
objects.size(); // This is the workaround to retrieve all objects
return objects;
} finally {
pm.close();
}
}
public static User findUser(String id) {
PersistenceManager pm = persistenceManager();
try {
User u = pm.getObjectById(User.class, id);
return u;
} finally {
pm.close();
}
}
public void persist() {
PersistenceManager pm = persistenceManager();
try {
pm.makePersistent(this);
} finally {
pm.close();
}
}
}
The RequestFactory interface itself is really simple
package com.test.shared;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
public interface UserOrderRequestFactory extends RequestFactory {
UserRequest userRequest();
}
so is the corresponding RequestContext
package com.test.shared;
import java.util.List;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.Request;
import com.test.server.User;
#Service(User.class)
public interface UserRequest extends RequestContext {
Request<List<UserProxy>> findAllUsers();
InstanceRequest<UserProxy, Void> persist();
}
Here is the proxy of user for the client side
package com.test.shared;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
#ProxyFor(com.test.server.User.class)
public interface UserProxy extends EntityProxy {
EntityProxyId<UserProxy> stableId();
String getName();
void setName(String name);
}
and finally my onModuleLoad() which first persists a user and then gets a list of all users.
public void onModuleLoad() {
final EventBus eventBus = new SimpleEventBus();
requestFactory = GWT.create(UserOrderRequestFactory.class);
requestFactory.initialize(eventBus);
UserRequest userRequest = requestFactory.userRequest();
UserProxy user = userRequest.create(UserProxy.class);
user.setName("Luigi");
userRequest.persist().using(user).fire( new Receiver<Void>()
{
#Override
public void onSuccess(Void arg0)
{
GWT.log("User persisted.");
}
});
userRequest = requestFactory.userRequest();
Request<List<UserProxy>> findAllUsersRequest = userRequest.findAllUsers();
findAllUsersRequest.fire( new Receiver<List<UserProxy>>() {
#Override
public void onSuccess(List<UserProxy> list) {
for(UserProxy u: list) {
GWT.log(u.getName());
}
}
});
Any input is welcome. I would be happy to receive any advice on this.
Thank you in advance.
While JPA seems to do this automatically it seems to be my job to advance the version counter in JDO. I added the following code to my persist routine in User.java
// JPA #Version does this automatically, but JDO #Version is not working like that. Not sure why.
if (version == null) {
version = 0l;
}
version++;
I am not sure if it matters but the #Version column = "VERSION" does not match the #Column(name = "version").
However GAE does not really have 'columns' as such and you can just ignore them by removing the column = "" and the #Column.
See http://gae-java-persistence.blogspot.com.au/2009/10/optimistic-locking-with-version.html

Resources