does the mapper interface necessary - ibatis

I am new in mybatis,and following mybatis3-user-guide.pdf.
I set up my first application.
However I found that I am not exactly know about the mapper interface.
By now,this is all the configuration for my application(take model User for example):
mybatis config.xml:
<configuration>
<typeAliases>
<typeAlias alias="User" type="com.king.mapper.User" />
</typeAliases>
<mappers>
<mapper resource="com/king/mapper/UserMapper.xml" />
</mappers>
</configuration>
UserMapper.xml:
<mapper namespace="com.king.mapper.UserMapper">
<select id="selectById" parameterType="int" resultMap="userMap">
select * from users where id = #{id}
</select>
<select id="selectAll" resultType="hashmap">
select * from users order by created_at desc
</select>
<insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into users (name,created_at,updated_at) values (#{name},current_timestamp,current_timestamp)
</insert>
<update id="update" parameterType="User">
update users set name = #{name},updated_at=current_timestamp where id = #{id}
</update>
<delete id="delete" parameterType="int">
delete from users where id = #{id}
</delete>
<resultMap id="userMap" type="User">
<result property="createDate" column="created_at" />
<result property="updateDate" column="updated_at" />
</resultMap>
</mapper>
Dao:
public abstract class AbstractSimpleDaoImpl<T> extends SqlSessionDaoSupport implements IDao<T> {
#Override
public T query(int id) {
return getSqlSession().selectOne(getMapperNamespace() + ".selectById", id);
}
#Override
public List<T> list() {
return getSqlSession().selectList(getMapperNamespace() + ".selectAll");
}
#Override
public int add(T entity) {
return getSqlSession().insert(getMapperNamespace() + ".insert", entity);
}
#Override
public int update(T entity) {
return getSqlSession().update(getMapperNamespace() + ".update", entity);
}
#Override
public void delete(T entity) {
getSqlSession().delete(getMapperNamespace() + ".delete", entity);
}
protected abstract String getMapperNamespace();
}
UserDao:
public class UserDao extends AbstractSimpleDaoImpl<User> {
private static String pack = "com.king.mapper.UserMapper";
#Override
protected String getMapperNamespace() {
return pack;
}
}
It worked. However I found that my example of mybatis will refer to the mapper interface.
It seems that I have to create a Interface named UserMapper in my above example.
But I wonder if it is necessary? and when I have to use it?
BTW,in my opinion,I found that what the mapper interface do just like the what the dao does. Since the dao and the interface may have so many methods with the same name.

You can create mapper interface UserMapper and avoid calling methods getSqlSession()... on your Dao object. So with mapper interface your xml configuration stay same but you can avoid Dao object at all. Just define interface like this:
public interface UserMapper {
public List<User> selectAll();
public User selectById(#Param("id") int id);
// rest is ommited
}
Names of methods must match with id of select/update/insert/detele in mapper file.
That's it.

Related

How to display tables from DB in Spring MVC Controller

I have referred to ->
Spring MVC how to display data from database into a table
My aim is to try and understand what is the syntax and process to create queries, and whether I'm correct.
The following code tries to display all Order entities.
#AutoWired
private OrderService orderService;
#RequestMapping("/")
//public String orderPage(Model model) {
// model.addAttribute("orderList", SomeApp.getStore().getOrderList());
// return "form/orderPage"};
// this is the code I am trying to translate below
#ResponseBody
public List<order> orderList(Map<String, Object> model) {
List<order> orderList = OrderService.findALl();
//orderRepository.findAll <- where does this come in? is it needed at all
return orderList;
}
If the Service layer is not being used, in my Repo do I only state
List<Order> findAll();
Additional Info:
Service layer is not used in this project and instead business logic will be in Controller (partly why I'm confused as to what code goes where)
You need to #Autowire the OrderRepository so that you can call orderRepository.findAll() in your Controller as shown below. For that, you also need to define the OrderRepository and Order Entity classes.
Controller:
#Controller
public class Controller {
#AutoWired
private OrderRepository orderRepository;
#RequestMapping("/")
#ResponseBody
public List<order> orderList(Map<String, Object> model) {
List<order> orderList = OrderService.findALl();
orderRepository.findAll();
return orderList;
}
}
Repository:
#Repository
public interface OrderRepository extends JpaRepository<Order, Integer> {
public Order findAll();
}
Entity:
#Entity
public class Order {
//add your entity fields with getters and setters
}
You can refer here for spring-data-jpa basic example.

Objectify throws IllegalArgumentException: No class 'com.app.db.client.model.ProductType' was registered

I am using Objectify 5.1.7 with Objectify Spring extension in my Spring-MVC application.
Here are my entity classes:
Product.java
#Entity
public class Product extends RelatedDataObject {
#Parent
private Ref<Vendor> vendor;
#Load
private Ref<ProductCategory> productCategory;
#Load
private Ref<ProductType> productType;
#Index
private String nativeId;
private Double costPrice;
private String modelId;
private String serviceLocations;
private Map<String, String> attributes;
public Double getCostPrice() {
return costPrice;
}
public String getModelId() {
return modelId;
}
public String getServiceLocations() {
return serviceLocations;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setCostPrice(Double costPrice) {
this.costPrice = costPrice;
}
public void setModelId(String modelId) {
this.modelId = modelId;
}
public void setServiceLocations(String serviceLocations) {
this.serviceLocations = serviceLocations;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public void addAttribute(String key, String value) {
if(key == null || value == null) {
throw new IllegalArgumentException("Key or value is null.");
}
if(attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.put(key, value);
}
public ProductCategory getProductCategory() {
return productCategory.get();
}
public ProductType getProductType() {
return productType.get();
}
public String getNativeId() {
return nativeId;
}
public void setNativeId(String nativeId) {
this.nativeId = nativeId;
}
public void setProductCategory(ProductCategory productCategory) {
this.productCategory = Ref.create(productCategory);
}
public void setProductType(ProductType productType) {
this.productType = Ref.create(productType);
}
public Vendor getVendor() {
return vendor.get();
}
public void setVendor(Vendor vendor) {
this.vendor = Ref.create(vendor);
}
public Key<Product> getKeyByParentVendor() {
if (getId() == null) {
throw new IllegalArgumentException("Product id is not set.");
}
if (vendor == null) {
throw new IllegalArgumentException("Parent vendor is not set.");
}
return Key.create(this.vendor.key(), Product.class, getId());
}
}
ProductType.java
#Entity
public class ProductType extends RelatedDataObject {
}
RelatedDataObject.java
public class RelatedDataObject extends DataObject {
private String description;
private boolean approved;
public RelatedDataObject() {
super();
approved = false;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isApproved() {
return approved;
}
public void setApproved(boolean approved) {
this.approved = approved;
}
}
DataObject.java
public class DataObject {
#Id
private String id;
#Index
private String name;
private boolean inactive;
public DataObject() {
super();
inactive = false;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public boolean isInactive() {
return inactive;
}
public void setInactive(boolean inactive) {
this.inactive = inactive;
}
}
And here is my spring bean xml configuration. All my entity classes are inside the package: com.app.db.client.client.model
<bean id="objectifyFactory" class="com.googlecode.objectify.spring.ObjectifyFactoryBean">
<property name="basePackage" value="com.app.db.client.model"/>
</bean>
<bean id="dbClient" class="com.app.db.client.impl.DbClientImpl">
<property name="objectifyFactory" ref="objectifyFactory"/>
</bean>
DBClientImpl.java
public class DbClientImpl implements DbClient {
private ObjectifyFactory objectifyFactory;
public void setObjectifyFactory(ObjectifyFactory objectifyFactory) {
this.objectifyFactory = objectifyFactory;
}
#Override
public <T extends DataObject> void createObject(T object) {
Objectify ofy = objectifyFactory.begin();
ofy.save().entity(object).now();
}
}
When the GAE devserver boots my spring MVC application, all entity classes are loaded. Here are the log messages:
[INFO] 2015-09-10 13:20:15 INFO ObjectifyFactoryBean:115 - Registered entity class [com.app.db.client.model.Product]
[INFO] 2015-09-10 13:20:15 INFO ObjectifyFactoryBean:115 - Registered entity class [com.app.db.client.model.ProductCategory]
[INFO] 2015-09-10 13:20:15 INFO ObjectifyFactoryBean:115 - Registered entity class [com.app.db.client.model.ProductType]
[INFO] 2015-09-10 13:20:15 INFO ObjectifyFactoryBean:115 - Registered entity class [com.app.db.client.model.Vendor]
When I try to save Product entity:
Product product = new Product();
product.setName("new product");
product.setProductType(productType);
product.setProductCategory(productCategory);
product.setNativeId(productNativeId);
product.setCostPrice(createProductParam.getCostPrice());
dbclient.createObject(product);
I get this error from Objectify:
[INFO] java.lang.IllegalArgumentException: No class 'com.app.db.client.model.ProductType' was registered
[INFO] at com.googlecode.objectify.impl.Registrar.getMetadataSafe(Registrar.java:120)
[INFO] at com.googlecode.objectify.impl.Keys.getMetadataSafe(Keys.java:53)
[INFO] at com.googlecode.objectify.impl.Keys.getMetadataSafe(Keys.java:62)
[INFO] at com.googlecode.objectify.impl.Keys.rawKeyOf(Keys.java:36)
[INFO] at com.googlecode.objectify.impl.Keys.keyOf(Keys.java:29)
[INFO] at com.googlecode.objectify.Key.create(Key.java:62)
[INFO] at com.googlecode.objectify.Ref.create(Ref.java:31)
[INFO] at com.app.db.client.model.Product.setProductType(Product.java:93)
Please help me resolve this problem.
I have got the same Issue and solved as in below steps.
1) Write your own ObjectifyFactoryBean (Just copy from https://github.com/marceloverdijk/objectify-appengine-spring) and update one line in afterPropertiesSet() method.
this.objectifyFactory = new ObjectifyFactory();
// Set the factory to ObjectifyService
ObjectifyService.setFactory(objectifyFactory);
2) Use this to in spring
<bean id="objectifyFactory" class="com.yourcompany.ObjectifyFactoryBean" >
<property name="basePackage" value="com.yourcompany.model" />
</bean>
3) Use objectifyFactory in your DAO classes as spring bean.
4) Add the Filter in your web.xml.
<!-- ObjectifyFilter filter -->
<filter>
<filter-name>objectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>objectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Explanation : I don't know how old version of Objectify work and based on that ObjectifyFactoryBean written, but in latest version of Objectify 5.x it internally use ObjectifyService in Ref operation, which was using the different objectifyFactory instance, So to make it use the same instance of objectifyFactory in whole application, we have set ObjectifyService.setFactory(objectifyFactory) inside our ObjectifyFactoryBean class.
A filter ObjectifyFilter is also require in web application, because this filter will make call to ObjectifyService.begin() for Objectify session, Normally we call ObjectifyService.begin() only when we do Datastore Operation and but is case of like Ref operation, ObjectifyFilter will do this job for us.
Hope this solve the issue!
The spring extension hasn't been updated since 2012 so it's entirely possible that it does not work with current versions of Objectify. I don't know - I would contact the author.
The problem is that your ProductType entity has not been registered. Presumably the spring extension is supposed to do that but isn't.
Like #stickfigure already mentioned this library hasn't been updated for a long time. That said the Objectify version it depends on - and tested with - is 2.2.x.
However from your logging it seems that the entities have been registered.
To verify if it works with the latest Objectify version you could:
clone the lib from https://github.com/marceloverdijk/objectify-appengine-spring
update the objectify version
run the tests
If that works you at least know the lib works with the latest Objectify version.

Is it appropriate to have EntityManager in a bundle class?

I want to know if it is efficient in JSF to define EntityManager and TypedQuery in a bundle class that is supposed to read messages from database?
What if I create an instance of a #Stateless bean and use its functions that return query results inside the bundle class?
UPDATE: Included some code:
protected class DBControl extends Control{
#Override
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
return new ArticleResources(locale);
}
protected class ArticleResources extends ListResourceBundle{
private Locale locale;
public ArticleResources (Locale locale){
this.locale = locale;
}
String language = locale.getLanguage();
#Override
protected Object[][] getContents(){
TypedQuery<ArticleLcl> query = em.createNamedQuery("ArticleLcl.findForLocale", ArticleLcl.class);
query.setParameter("lang", language);
List<ArticleLcl> articles = query.getResultList();
Object[][] allArticles = new Object[articles.size()][3];
int i = 0;
for(Iterator<ArticleLcl> it = articles.iterator(); it.hasNext();){
ArticleLcl article = it.next();
allArticles[i] = new Object[]{article.getArticleId().getArticleId().toString(),article.getArticleTitle()};
messages.put(article.getArticleId().getArticleId().toString(),article.getArticleTitle());
i++;
}
return allArticles;
}
}
By the way this code does not work and my entity manager is null. But I wonder am I doing the right thing?

How to call another method in the pojo class setter method [session file uploading application] of Hibernate and struts 2

Hi Friends i am developing an web application which uses hibernate and struts2. i am creating photo album i successfully done that with out using hibernate but, with hibernate it is having problem while inserting to the database. the module works like this as soon as the file uploaded it will insert the FileName, Contenttype,id and it suppose to insert the Image File(byte[]) Content also but it is showing Null in table value.. my code goes like this...
#Entity
#Table(name="PHOTOALBUM")
public class User implements Serializable {
#Id
#GeneratedValue
#Column(name="PHOTO_ID")
private Long id;
#Column(name="IMAGE")
private byte[] Image;
#Column(name="CONTENT_TYPE")
private String userImageContentType;
#Column(name="PHOTO_NAME")
private String userImageFileName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserImageFileName() {
return userImageFileName;
}
public void setUserImageFileName(String userImageFileName) {
this.userImageFileName = userImageFileName;
}
public String getUserImageContentType() {
return userImageContentType;
}
public void setUserImageContentType(String userImageContentType) {
this.userImageContentType = userImageContentType;
}
public byte[] getImage() {
return Image;
}
public void setImage(byte[] Image) {
Image=Change(this.getUserImage());
this.Image = Image;
}
#Transient
private File userImage;
public File getUserImage() {
return userImage;
}
public void setUserImage(File userImage) {
this.userImage = userImage;
}
public byte[] Change(File userImage)
{
// userImage=this.getUserImage();
// String name=userImage.getName();
// long len=userImage.length();
byte[] bFile = new byte[(int) userImage.length()];
try {
FileInputStream fileInputStream = new FileInputStream(userImage);
fileInputStream.read(bFile);
fileInputStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
// System.out.println("The Name Of File In Pojo Class Is:="+ name);
//System.out.println("The Length Of File In Pojo Class Is:="+ len);
//System.out.println("The Content Of File In Pojo Class Is:="+ bFile);
return bFile;
}
}
and i am saving the values like this
public class UserDAOImpl implements UserDAO {
#SessionTarget
Session session;
#TransactionTarget
Transaction transaction;
/**
* Used to save or update a user.
*/
#Override
public void saveOrUpdateUser(User user) {
try {
session.saveOrUpdate(user);
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
/**
* Used to delete a user.
*/
#Override
public void deleteUser(Long userId) {
try {
User user = (User) session.get(User.class, userId);
session.delete(user);
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
/**
* Used to list all the users.
*/
#SuppressWarnings("unchecked")
#Override
public List<User> listUser() {
List<User> courses = null;
try {
courses = session.createQuery("from User").list();
} catch (Exception e) {
e.printStackTrace();
}
return courses;
}
/**
* Used to list a single user by Id.
*/
#Override
public User listUserById(Long userId) {
User user = null;
try {
user = (User) session.get(User.class, userId);
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
}
the struts action mapping goes like this...
\<package name="default" extends="hibernate-default">
<action name="saveOrUpdateUser"method="saveOrUpdate"class="com.srikanth.web.UserAction">
<result name="success" type="redirect">listUser</result>
</action>
<action name="listUser" method="list" class="com.srikanth.web.UserAction">
<result name="success">/register.jsp</result>
</action>
<action name="editUser" method="edit" class="com.srikanth.web.UserAction">
<result name="success">/register.jsp</result>
</action>
<action name="deleteUser" method="delete" class="com.srikanth.web.UserAction">
<result name="success" type="redirect">listUser</result>
</action>
</package>
and my jsp goes like this
\<s:form action="saveOrUpdateUser">
<s:push value="user">
<s:hidden name="id" />
<s:file name="userImage" label="User Image" />
<s:submit />
</s:push>
</s:form>
<s:iterator value="userList" status="userStatus">
<s:property value="id" />
<s:property value="userImageFileName" />
<s:property value="userImageContentType" />
<img src='<s:property value="userImage" />' alt"" />
<s:url id="deleteURL" action="deleteUser">
<s:param name="id" value="%{id}"></s:param>
</s:url> <s:a href="%{deleteURL}">Delete</s:a>
</s:iterator>
I am trying to call the Change Method so that it convert the file to byte[] and stored it in byte[] Image variable using setter but it is not working....
So please help me with this one .....
thanks in advance
As per my understand of question the problem is only inserting file into table. Copy & paste the Change() method into com.srikanth.web.UserAction class as you are using this action for every DB transaction. use Change() method before going to insert/update in DB.
For example:
public class UserAction extends ActionSupport{
//variable to get file from jsp
private File uploadedImage;
.....
//setters & getters for uploadedImage
#Override
public String gsexecute() throws Exception {
User user = new User();
//set image value as byteArray
user.setImage(Change(uploadedImage));
//insert or update DB here
return SUCCESS;
}
public byte[] Change(File userImage)
{
// userImage=this.getUserImage();
// String name=userImage.getName();
// long len=userImage.length();
byte[] bFile = new byte[(int) userImage.length()];
try {
FileInputStream fileInputStream = new FileInputStream(userImage);
fileInputStream.read(bFile);
fileInputStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
// System.out.println("The Name Of File In Pojo Class Is:="+ name);
//System.out.println("The Length Of File In Pojo Class Is:="+ len);
//System.out.println("The Content Of File In Pojo Class Is:="+ bFile);
return bFile;
}
}
And make sure that the table column should support the byte array insert. Ex: use BLOB column type for MYSQL.

Failed to create an instance of Service via deferred binding

I have been trying to build a GWT / Google App Engine web app using the mvp4g framework.
I keep getting an error about Failing to create an instance of my Service via deferred binding.
My Acebankroll.gwt.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='acebankroll'>
<inherits name='com.google.gwt.user.User'/>
<inherits name="com.google.gwt.i18n.I18N"/>
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<inherits name='com.mvp4g.Mvp4gModule'/>
<entry-point class='com.softamo.acebankroll.client.AceBankroll'/>
<source path='client'/>
</module>
My Entry Module looks like:
public class AceBankroll implements EntryPoint {
public void onModuleLoad() {
Mvp4gModule module = (Mvp4gModule)GWT.create( Mvp4gModule.class );
module.createAndStartModule();
RootPanel.get().add((Widget)module.getStartView());
}
}
Error Trace
I post the complete error trace as an answer.
FAQ and Trials
I have read that the next list of common mistakes may cause this error:
The ServiceAsync interfaces have methods with return values. This is wrong, all methods need to return void.
The Service interfaces don't extend the RemoteService interface.
The methods in the ServiceAsync interfaces miss the final argument of AsyncCallback.
The methods on the two interfaced, ExampleService and ExampleServiceAsync, don't match up exactly (other than the return value and AsyncCallback argument)
I have checked all the above conditions and did not find the problem.
How do you insert your services in the presenters?
Here is a snippet illustrating how I do inject the service in my presenter classes.
protected MainServiceAsync service = null;
#InjectService
public void setService( MainServiceAsync service ) {
this.service = service;
}
Do you have the required libraries?
Yes, I have commons-configuration-1.6.jar, commons-lang-2.4.jar and mvp4g-1.1.0.jar in my lib directory.
Does your project compiles?
Yes, it does compile. I use Eclipse with GWT/Google App Engine plugin. Next I post my .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" output="test-classes" path="test"/>
<classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/commons-configuration-1.6.jar"/>
<classpathentry kind="lib" path="lib/commons-lang-2.4.jar"/>
<classpathentry kind="lib" path="lib/mvp4g-1.1.0.jar"/>
<classpathentry kind="lib" path="test/lib/emma.jar"/>
<classpathentry kind="lib" path="test/lib/junit-4.5.jar"/>
<classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/testing/appengine-testing.jar"/>
<classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api.jar"/>
<classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api-labs.jar"/>
<classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api-stubs.jar"/>
<classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-local-runtime.jar"/>
<classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>
Are your Bean Serializable?
Yes, they are serializable. They implements the next interface:
public interface BasicBean extends Serializable {
public String getId();
public void copy(BasicBean ob);
}
They all have an empty argument constructor. Some of them have two constructors. One without arguments and one with arguments.
Some of them implement this interface
public interface NameObject extends BasicBean, BaseOwnedObject, Comparable<NameObject> {
public String getName();
public void setName(String name);
public abstract int compareTo(NameObject ob);
}
Can the Comparable cause problems?
How does your service code looks like?
I post my service code:
MainService
#RemoteServiceRelativePath( "main" )
public interface MainService extends RemoteService {
public List<UserBean> getUsers();
public void deleteUser(UserBean user);
public void createUser(UserBean user);
public void updateUser( UserBean user );
public String authenticate(String username, String password);
public boolean isSessionIdStillLegal(String sessionId);
public void signOut();
public boolean userAlreadyExists(String email);
public UserBean getByEmail(String email);
public void confirmUser(String email);
public UserBean getUserById(String id);
}
MainServiceAsync
public interface MainServiceAsync {
public void getUsers(AsyncCallback<List<UserBean>> callback);
public void deleteUser(UserBean user, AsyncCallback<Void> callback);
public void createUser(UserBean user, AsyncCallback<Void> callback);
public void updateUser( UserBean user, AsyncCallback<Void> callback);
public void authenticate(String username, String password, AsyncCallback<String> callback);
public void isSessionIdStillLegal(String sessionId, AsyncCallback<Boolean> callback);
public void signOut(AsyncCallback<Void> callback);
public void userAlreadyExists(String email, AsyncCallback<Boolean> callback);
public void getByEmail(String email, AsyncCallback<UserBean> callback );
public void confirmUser(String email, AsyncCallback<Void> callback );
public void getUserById(String id, AsyncCallback<UserBean> callback);
}
Basic Bean
import java.io.Serializable;
public interface BasicBean extends Serializable {
public String getId();
public void copy(BasicBean ob);
}
User Bean
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class UserBean implements BasicBean {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
protected Long ident;
#Persistent
private String name = null;
#Persistent
private String email = null;
#Persistent
private boolean confirmed = false;
#Persistent
private String password = null;
public UserBean() { }
public String getId() {
if( ident == null ) return null;
return ident.toString();
}
public void setId(String id) {
this.ident = Long.parseLong(id);
}
public String getEmail( ) { return email; }
public void setEmail(String email) { this. email = email; }
public String getName() { return name; }
public void setName(String name) { this. name = name; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password;}
public boolean isConfirmed() { return confirmed;}
public void setConfirmed(boolean confirmed) {this.confirmed = confirmed;}
public void copy(BasicBean ob) {
UserBean user = (UserBean) ob;
this.name = user.name;
this.email = user.email;
this.password = user.password;
}
}
Next I post an extract of web.xml
Note. I have 7 other services. I am using the module functionality of MVP4G. I have other servlets defined for each module in web.xml
<servlet>
<servlet-name>mainServlet</servlet-name>
<servlet-class>com.softamo.acebankroll.server.MainServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mainServlet</servlet-name>
<url-pattern>/acebankroll/main</url-pattern>
</servlet-mapping>
Server
BaseServiceImpl
public abstract class BaseServiceImpl extends RemoteServiceServlet {
protected Map users = new HashMap();
protected static final MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
protected static final Logger log = Logger.getLogger(BaseServiceImpl.class.getName());
protected String getSessionId() {
return getThreadLocalRequest().getSession().getId();
}
protected String getCurrentUserId() {
String id = getSessionId();
UserBean user = (UserBean) users.get(id);
if(user!=null)
return user.getId();
return null;
}
protected void saveBaseObject(BasicBean ob) {
PersistenceManager pm = JdoUtil.getPm();
String sessionId = getSessionId();
UserBean user = (UserBean) users.get(sessionId);
if(user!=null) {
String user_id = user.getId();
((BaseOwnedObject)ob).setUserId(user_id);
pm.makePersistent(ob);
}
}
protected void deleteBaseObject(Class classname, String id) {
PersistenceManager pm = JdoUtil.getPm();
pm.deletePersistent( pm.getObjectById(classname, Long.parseLong(id) ));
}
protected List getAll(Class class_name) {
PersistenceManager pm = JdoUtil.getPm();
pm.setDetachAllOnCommit(true);
Query q = pm.newQuery(class_name);
if(q==null)
return new ArrayList<BasicBean>();
q.setFilter("userId == userIdParam");
q.declareParameters("String userIdParam");
String userId = getCurrentUserId();
return (List) q.execute(userId);
}
public boolean isSessionIdStillLegal(String sessionId) {
return (users.containsKey(sessionId))? true : false;
}
public void signOut() {
String id = getSessionId();
synchronized(this) {
users.remove(id);
}
}
public BasicBean getObjectById(Class classname, String id) {
BasicBean result = null;
PersistenceManager pm = JdoUtil.getPm();
pm.setDetachAllOnCommit(true);
result = pm.getObjectById(classname, Long.parseLong(id) );
return result;
}
}
MainServiceImpl
public class MainServiceImpl extends BaseServiceImpl implements MainService {
public MainServiceImpl() {}
public String authenticate(String username, String password) {
PersistenceManager pm = JdoUtil.getPm();
UserBean user = getByEmail(username);
if(user==null || !user.isConfirmed())
return null;
String hashFromDB = user.getPassword();
boolean valid = BCrypt.checkpw(password, hashFromDB);
if(valid) {
String id = getSessionId();
synchronized( this ) {
users.put(id, user) ;
}
return id;
}
return null;
}
public void deleteUser(UserBean user) {
deleteBaseObject(UserBean.class, user.getId());
}
public List<UserBean> getUsers() {
PersistenceManager pm = JdoUtil.getPm();
pm.setDetachAllOnCommit(true);
Query q = pm.newQuery(UserBean.class);
if(q==null)
return new ArrayList<UserBean>();
return (List) q.execute();
}
public boolean userAlreadyExists(String email) {
return (getByEmail(email)!=null) ? true : false;
}
public void updateUser(UserBean object) {
saveBaseObject(object);
}
public void confirmUser(String email) {
PersistenceManager pm = JdoUtil.getPm();
UserBean user = getByEmail(email);
if(user!=null) {
user.setConfirmed(true);
pm.makePersistent(user);
}
}
public void createUser(UserBean user) {
PersistenceManager pm = JdoUtil.getPm();
String sessionId = getSessionId();
// Only store it if it does not exists
if( (getByEmail(user.getEmail()))==null) {
String hash = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());
user.setPassword(hash);
pm.makePersistent(user);
synchronized( this ) {
users.put(sessionId, user);
}
}
}
public UserBean getByEmail(String email) {
return new MyAccountServiceImpl().getByEmail(email);
}
public UserBean getUserById(String id) {
return new MyAccountServiceImpl().getUserById(id);
}
}
SOLUTION
Apparently the Google App Engine Annotations in my Bean classes were causing the problem. Removing the annotation from the client side code solved the issue. What I do know if I have the classes with the JDO notation in the server side. That it is to say the beans are plain data transfere object which get cloned into object with JDO annotations in the server side.
I am literally stacked. I do not know what to try. Any help is really appreciated!
If your service methods contains POJO's they can cause you problems, they must have a zero argument constructor or no constructor defined. Also they must implement either IsSerializable or Serializable.
You can trie to create the service manually with:
MainServiceAsync service = GWT.create(MainService.class);
And maybe post the MainService classes.
Edited:
This is an output from the treelogger with a deferred binding failing, and it is outputed into the console when you do a gwt compile. You can also see this output in the devmode console if you run in hosted mode. Always check the first error, because the others are most of the time caused by the first error.
Compiling module se.pathed.defa.DefaultGwtProject
Scanning for additional dependencies: file:/C:/Users/Patrik/workspace/skola-workspace/DefaultGwtProject/src/se/pathed/defa/client/DefaultGwtProject.java
Computing all possible rebind results for 'se.pathed.defa.client.GreetingService'
Rebinding se.pathed.defa.client.GreetingService
Invoking com.google.gwt.dev.javac.StandardGeneratorContext#16c6a55
Generating client proxy for remote service interface 'se.pathed.defa.client.GreetingService'
[ERROR] se.pathed.defa.shared.UserBean is not default instantiable (it must have a zero-argument constructor or no constructors at all) and has no custom serializer. (reached via se.pathed.defa.shared.UserBean)
[ERROR] se.pathed.defa.shared.UserBean has no available instantiable subtypes. (reached via se.pathed.defa.shared.UserBean)
[ERROR] subtype se.pathed.defa.shared.UserBean is not default instantiable (it must have a zero-argument constructor or no constructors at all) and has no custom serializer. (reached via se.pathed.defa.shared.UserBean)
[ERROR] Errors in 'file:/C:/Users/Patrik/workspace/skola-workspace/DefaultGwtProject/src/se/pathed/defa/client/DefaultGwtProject.java'
[ERROR] Line 37: Failed to resolve 'se.pathed.defa.client.GreetingService' via deferred binding
Scanning for additional dependencies: jar:file:/C:/eclipse/plugins/com.google.gwt.eclipse.sdkbundle.2.0.3_2.0.3.v201002191036/gwt-2.0.3/gwt-user.jar!/com/google/gwt/core/client/impl/SchedulerImpl.java
[WARN] The following resources will not be created because they were never committed (did you forget to call commit()?)
[WARN] C:\Users\Patrik\AppData\Local\Temp\gwtc301646733929273376.tmp\se.pathed.defa.DefaultGwtProject\compiler\se.pathed.defa.client.GreetingService.rpc.log
[WARN] For the following type(s), generated source was never committed (did you forget to call commit()?)
[WARN] se.pathed.defa.client.GreetingService_Proxy
[ERROR] Cannot proceed due to previous errors
This can happen if anything that is in your client package has an import that is not whitelisted. For example i hit this because my autoimport imported an apache commons lang class into my client code.
One would have to look at their imports to make sure nothing odd is in the client code.
GWT projects are structured like:
com.app.client
com.app.server
you can't having anything that not GWT compatible in client.

Resources