Why is it mandatory to have both getters and setters for a field in RF Proxy interfaces? For some fields (like plain text password), you want setters only.
e.g.
#ProxyFor(value = User.class)
public interface UserProxy extends ValueProxy {
void setPassword(String password);
}
User class has both getters and setters.
public class User implements Serializable {
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
When I set the password on proxy, I get an IllegalArgumentException:
UserProxy user = userRequest.create(UserProxy.class);
user.setPassword("abc")
Above code results in following error:
java.lang.IllegalArgumentException: password
at com.google.web.bindery.autobean.shared.impl.AutoBeanCodexImpl.doCoderFor(AutoBeanCodexImpl.java:525)
at com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.setProperty(AbstractAutoBean.java:276)
...
...
This error goes away if I add a 'getPassword()' method in UserProxy interface but that defeats the purpose. Any suggestion would be helpful.
AFAIK you can have a getter without a setter but not the other way round.
See here and this issue.
Related
I have a simple User model whose fields are annotated with play validation annotations and morphia annotations like below.
import play.data.validation.*;
import play.modules.morphia.Model;
import com.google.code.morphia.annotations.*;
#Entity
public class User extends Model{
#Id
#Indexed(name="USERID", unique=true)
public ObjectId userId;
#Required public String userName;
#Email
#Indexed(name="USEREMAIL", unique=true)
#Required public String userEmail;
}
Now I have a service which has a CreateNewUser method responsible for persisting the data. I have used Morphia plugin for the dao support. But the problem is that User Document gets persisted in mongo-db even if userName or userEmail is NULL. Also #Email validation does not happen
// Below code is in app/controllers/Application.java
User a = new User();
a.userName = "user1";
// calling bean to create user, userService is in app/service/UserService
userService.createNewUser(a);
It does not work even after adding #valid and validation.hasErrors() check.Below code is in app/service/UserService
public void createNewUser(#Valid User user) {
if (Validation.hasErrors()) {
System.out.println("has errors");
} else {
// TODO Auto-generated method stub
userDao.save(user);
}
}
Now I understand, createNewUser is not an action.
So you can enforce object validation:
public void createNewUser(User user) {
final Validation.ValidationResult validationResult = validation.valid(user);
if (validationResult.ok) {
userDao.save(user);
} else {
System.out.println("has errors");
}
}
api: http://www.playframework.org/documentation/api/1.2.5/play/data/validation/Validation.html
Old answer
You forgot an annotation to validate the object and you must check if the form has errors.
public void createNewUser(#Valid User user) {
if(validation.hasErrors()) ...
source: http://www.playframework.org/documentation/1.2.5/validation#objects
I need to pass a class object through the gwt rpc connection as a generic but it seems that rpc does not cooperate with it. The class is serialized using the java.io.Serializable. I have checked it using the gwt IsSerializable but i still have the error.
Here is my code
MySource.java
#SuppressWarnings("serial")
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class MySource implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private String userId;
#Persistent
private String title;
#Persistent
private String description;
#Persistent
private String blobKey;
#Persistent
private String youtubeLink;
#Persistent
private String personalLink;
#Persistent
private Date submitedDate;
#Persistent
private float price;
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getBlobKey() {
return blobKey;
}
public void setBlobKey(String blobKey) {
this.blobKey = blobKey;
}
public String getYoutubeLink() {
return youtubeLink;
}
public void setYoutubeLink(String youtubeLink) {
this.youtubeLink = youtubeLink;
}
public String getPersonalLink() {
return personalLink;
}
public void setPersonalLink(String personalLink) {
this.personalLink = personalLink;
}
public Date getSubmitedDate() {
return submitedDate;
}
public void setSubmitedDate(Date submitedDate) {
this.submitedDate = submitedDate;
}
public Long getId() {
return id;
}
}
AndroidSource.java
#SuppressWarnings("serial")
#PersistenceCapable
public class AndroidSource extends MySource{
public AndroidSource() {
super();
}
}
CategoryBrowseService.java which is the remoteservice model
#RemoteServiceRelativePath("categoryService")
public interface CategoryBrowseService extends RemoteService{
ArrayList<MySource> getSourceList(Class<? extends MySource> classType);
}
CategoryBrowseServiceAsync.java
public interface CategoryBrowseServiceAsync {
void getSourceList(Class<? extends MySource> classType,
AsyncCallback<ArrayList<MySource>> callback);
}
CategoryBrowsePresenter.java where the rpc is called
private void retrieveSources(Class<? extends MySource> classType) {
CategoryBrowseServiceAsync rpcService = GWT.create(CategoryBrowseService.class);
rpcService.getSourceList(classType, new AsyncCallback<ArrayList<MySource>>() {
#Override
public void onFailure(Throwable caught) {
Window.alert("Ooops!!!Sorry!Something went wrong.I am still beta!");
}
#Override
public void onSuccess(ArrayList<MySource> result) {
sourceList = result;
display.setSourceContent(sourceList);
}
});
}
CategoryBrowseServiceImpl.java
#SuppressWarnings("serial")
public class CategoryBrowseServiceImpl extends RemoteServiceServlet implements CategoryBrowseService{
private SourceDatastore dataStore;
public CategoryBrowseServiceImpl() {
dataStore = new SourceDatastore();
}
#Override
public ArrayList<MySource> getSourceList(Class<? extends MySource> classType) {
return dataStore.getSources(classType);
}
}
Here is the error that i get.
Compiling module com.sourcebay.SourceBay
Scanning for additional dependencies: file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java
Computing all possible rebind results for 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
Rebinding com.sourcebay.client.model.mybay.browse.CategoryBrowseService
Invoking generator com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator
Generating client proxy for remote service interface 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
[ERROR] java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] java.lang.Class<T> has no available instantiable subtypes. (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] subtype java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] Errors in 'file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java'
[ERROR] Line 75: Failed to resolve 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService' via deferred binding
The paradox is that when i am running my application through the eclipse plugin everything works fine. Could anyone help me please? I have checked to fix the problem through the DTO solution without any success. Moreover i have tried to implement a CustomFieldSerializer as Google suggests without any success too.
Thanks in advance,
Stefanos Antaris
P.S. Sorry for the huge post :-)
Well the problem is that you trying to transport a Class object over the network. I have no idea why it is working in dev mode (I've tried it on local project and it failed), but it shouldn't work. You have to use something else instead of Class name for example String, which will contain a name of class. Theoretically it can work if you create CustomFieldSerializer for Class, but using String instead of Class will be easier.
Classes with persistence annotations can work well on the server side, but if you want to pass its data to the client you must create a plain java serializable class to transport data from server to client.
As noted in the previous answer, persistence annotations are not supported in the client side, as they cannot be translated to equivalent javascript code (and it makes sense since the client doesn't have the responsability of persistence).
It could be that the persistence-related annotations in MySource.java make it implossible to translate to javascript. Try removing the annotations to see if it's related. Also make sure that MySource.java is in a package declared as translatable in the module xml file ("source" element).
Try using implements Serializable for defining you class.
I mean like this:
public class AndroidSource extends MySource implements Serializable{
public AndroidSource() {
super();
}
}
Your RPC Services must deal just with Serializable Objects. Domain classes are not translatable to JavaScript So GWT can't send and receive via network (RPC Protocole) such objects. You need to create DTO classes (wich shadows domain class) implementing java.io.Serializable and then reconfigure all your RPC Service to use in input DTOs and output DTOs. Good Luck for your project.
How to enable ZK Page to bind with non public properties of bean.
Say I have a domain object called Book which looks like
class Book{
private String name;
protected String getName(){
return name;
}
protected void setName(String name){
this.name = name;
}
}
I want to be able to bind a textbox using #{book.name} , at present I think to enble binding i will need to make the getter and setter as public.
Frameworks like hibernate can operate on non public properties as well, so why has zk choosen not too, an configuration change possible to enable this ??
Any suggestions would be great.
Thanks
Sudarshan
Subclass it with making these accessors public and use the subclass instead of class Book.
Domain model definition:
public interface Book {
// some public methods you want to expose
}
Domain model implementation:
// This class is of package visibility
class BookSomewhatSpecificImplementation implements Book {
private String name;
// Note that they are package-scoped.
String getName(){
return name;
}
void setName(String name){
this.name = name;
}
}
Object factory:
public final class DomainModelFactory {
public static Book createBook(/* Some parameters */) {
return new BookSomewhatSpecificImplementation();
}
private DomainModelFactory() {}
}
Summary: you should program all other modules against Book interface. You can still use reflection for model implementation. To produce do mane objects use the factory.
On my website using Play!, I have an Admin part. All Admin controllers have a #With and a #Check annotation.
When disconnected, everything goes fine.
When connected, each time I load a page (any page, admin or not), a JPAException is raised.
Here is the Admin checker :
public class Security extends Secure.Security {
static boolean authentify(String username, String password) {
return User.connect(username, password) != null;
}
static boolean check(String profile) {
User user = User.find("byLogin", connected()).<User>first(); /**line 12**/
renderArgs.put("user", user.login);
if ("admin".equals(profile)) {
return user.role == Role.Admin;
} else if ("manager".equals(profile)) {
return user.role == Role.Manager || user.role == Role.Admin;
} else if ("user".equals(profile)) {
return true;
}
return false;
}
}
Here is the exception :
JPA error
A JPA error occurred (The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the #javax.persistence.Entity annotation are found in the application.):
play.exceptions.JPAException: The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the #javax.persistence.Entity annotation are found in the application.
at play.db.jpa.JPA.get(JPA.java:22)
at play.db.jpa.JPA.em(JPA.java:51)
at play.db.jpa.JPQL.em(JPQL.java:16)
at play.db.jpa.JPQL.find(JPQL.java:44)
at models.User.find(User.java)
at controllers.Security.check(Security.java:12)
at play.utils.Java.invokeStaticOrParent(Java.java:159)
at controllers.Secure$Security.invoke(Secure.java:193)
at {play}/framework/templates/tags/404.html.(line:1)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.GroovyTemplate$ExecutableTemplate.invokeTag(GroovyTemplate.java:347)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:247)
at play.templates.Template.render(Template.java:26)
at play.server.PlayHandler.serve404(PlayHandler.java:634)
at Invocation.HTTP Request(Play!)
This actually doesn't bother the application (it works fine), but I really don't know why this occurs...
Thanks in advance !
EDIT :
The User class code :
#Entity
public class User extends Model {
#Email
public String email;
#Required #Password
public String password;
public String fullname;
#Required #Column(unique=true)
public String login;
#Enumerated(EnumType.STRING)
public Role role=Role.User;
public static User connect(String login, String password) {
return find("byLoginAndPassword", login, password).first();
}
#Override
public String toString() {
return login;
}
}
Have you uncommented the following code in your application.conf ?
db=mem
Play starts the JPA context only if database is activated in application.conf.
I have a method that can be called if the person has a specific role and they are associated with a particular group in JIRA. Since the groups in JIRA are dynamic, I can't have a role per JIRA group.
#DeclareRoles({
FileServerRoles.FILE_ADDER,
FileServerRoles.FILE_ADDER_ALL,
FileServerRoles.FILE_VIEWER,
FileServerRoles.FILE_VIEWER_ALL})
public final class FileServerRoles {
/**
* A user that can add files to the system.
*/
public static final String FILE_ADDER = "file-adder";
/**
* A user that can add any files to the system.
*/
public static final String FILE_ADDER_ALL = "file-adder-all";
/**
* A user that can view files in the system.
*/
public static final String FILE_VIEWER = "file-viewer";
/**
* A user that can view all files in the system.
*/
public static final String FILE_VIEWER_ALL = "file-viewer-all";
}
I am declaring all of the roles using #DeclareRoles.
#Decorator
public class FileServerServiceProjectAuthorizationDecorator implements FileServerService {
private static Logger LOGGER = LoggerFactory.getLogger(FileServerServiceProjectAuthorizationDecorator.class);
#Inject
#Delegate
#Any
FileServerService delagate;
#Inject
#CurrentUser
Set<JiraProjectReference> currentUserProjectReferences;
#Resource
SessionContext sessionContext;
void verifyProjectKey(final String projectKey) {
for (final JiraProjectReference projectReference : currentUserProjectReferences) {
if (projectReference.getKey().equalsIgnoreCase(projectKey)) {
return;
}
}
throw new IllegalArgumentException("user not in the project");
}
#RolesAllowed({FileServerRoles.FILE_ADDER, FileServerRoles.FILE_ADDER_ALL})
#Override
public FileAddStatus addFileToRepository(final String projectKey, final String issueKey, final String fileName, final String mimeType, final File file) {
if (!sessionContext.isCallerInRole(FileServerRoles.FILE_ADDER_ALL)) {
verifyProjectKey(projectKey);
}
return delagate.addFileToRepository(projectKey, issueKey, fileName, mimeType, file);
}
#RolesAllowed({FileServerRoles.FILE_VIEWER, FileServerRoles.FILE_VIEWER_ALL})
#Override
public FileDescriptor retrieveFileFromRepository(final String projectKey, final String issueKey, final UUID uuid, final String fileName) {
if (!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL)) {
verifyProjectKey(projectKey);
}
return delagate.retrieveFileFromRepository(projectKey, issueKey, uuid, fileName);
}
}
!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL) always throws IllegalStateException:
Caused by: java.lang.IllegalStateException: No mapping available for role reference file-viewer-all
at com.sun.ejb.containers.EJBContextImpl.isCallerInRole(EJBContextImpl.java:458)
at edu.wvu.esd.swordfish.web.service.FileServerServiceProjectAuthorizationDecorator.retrieveFileFromRepository(FileServerServiceProjectAuthorizationDecorator.java:59)
... 89 more
I have had no problem with any of the roles when that are referenced in #RolesAllowed. I have also tried moving the roles declaration into web.xml. There aren't many references to the error on google.
Has anyone seen this? What was your solution?
I was receiving the same "No mapping available for role reference" error when calling the isCallerInRole(roleName) method within an EJB in GlassFish 3.1. What fixed it for me was adding the appropriate #DeclareRoles annotation to my EJB. If the role name passed to isCallerInRole is not in #DeclareRoles, an IllegalStateException gets thrown. I'm not sure how security works within a decorator but #DeclareRoles was the key for me.
Here is a simple example:
#Stateless
#LocalBean
#DeclareRoles({"user", "admin"})
public class ExampleEJB {
#Resource
private SessionContext sessionContext;
public boolean isUserInRole(String roleName) {
return sessionContext.isCallerInRole(roleName);
}
}