Play! 1.2.5 with mongodb | Model Validation not happening - mongodb

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

Related

Can I write my own Queries in a Spring boot web app?

I'm making my first springboot web app, and trying to display some information from a postgresql server. When trying to get some information out of the database, it returns an empty list. By what I can see in the console, it tries to query with the wrong parameters.
In my DB I have a table with three fields: "userId", "firstName", and "surName".
From what i can understand, Hibernate tries to query with the parameters "users0_.user_id", "users0_user_id", "users0_.sur_name".
To fix this i want to write my own queries or fix the current one. How do I do this?
As you can see I have checked the results of the query with some System.Out.print statements.
The first one returned a list.size() of 0,
and the second one returned a value of null.
Console displaying what I think is the query info
This is the function in my UserController class used to display the users' info.
#RequestMapping("/users")
public String getUsers(Model model) {
List <users>users = (List<users>) userServ.listAll();
System.out.print("THE SIZE WITH STRING CONCATINATION IS: " + users.size());
model.addAttribute("users", users);
System.out.print("THE NAME OF USER WITH INDEX =2 IS: " + userServ.getById(2).getFirstName());
return "showUsers";
}
The entity/domain-class for a user:
#Entity
#Table(name="users")
public class users implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long userId;
private String firstName;
private String surName;
private long getId() { return userId; }
public void setId(long id) {this.userId = id;}
public String getFirstName() { return firstName; }
public String getSurName() { return surName; }
public void setSurname(String surName) {this.surName = surName; }
}
This is the interface of the repository used to retrieve users from the DB:
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.CrudRepository;
import com.svein.models.users;
public interface UserRepository extends CrudRepository<users, Long> {
}
This is the service class for the users:
#Service
public class UserServiceImp implements userService{
#Autowired
private UserRepository userRepo;
#Override
public List<users> listAll() {
List<users> users = new ArrayList<>();
userRepo.findAll().forEach(users::add);
return users;
}
#Override
public users getById(long id) {
return userRepo.findById(id).orElseGet(users::new);
}
#Override
public users saveOrUpdate(users user) {
userRepo.save(user);
return null;
}
#Override
public void delete(Long id) {
userRepo.deleteById(id);
}
}
I was hoping to adjust or replace the current query, but maybe there is something alse wrong with the code. As I said, I'm quite new to this, but thought it was weird that i had not written a single line of SQL, and in a different project THAT showed signs of retrieving the right information(from a different DB). How does the class know what to query for?
You need to add an #Query annotation on top of query function you want to write in your UserRepository class.
For e.g
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.CrudRepository;
import com.svein.models.users;
public interface UserRepository extends CrudRepository<users, Long> {
#Query("Select * from users")
List<users> findAllUsers();
}
Alternatively in your UserServiceImpl, userRepo.findAll() should work.You do not need to loop through each user and return it to list. You should simply return userRepo.findAll().
Following url would give you more idea about how to write your own query.
https://www.baeldung.com/spring-data-jpa-query

#DBRef Lazy loading is not working

I am using spring data mongodb, i trying to load entities lazy using db reference annotation of spring data mongodb,but it is not working.
still entity is loaded eagerly,what am i doing wrong here?
My preference domain
public class Preference extends BaseEntity {
/**
*
*/
private static final long serialVersionUID = 1L;
#DBRef(lazy = true)
User user;
MetadataEnum preferenceType;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public MetadataEnum getPreferenceType() {
return preferenceType;
}
public void setPreferenceType(MetadataEnum preferenceType) {
this.preferenceType = preferenceType;
}
public List<Subtype> getSubtypes() {
return subtypes;
}
public void setSubtypes(List<Subtype> subtypes) {
this.subtypes = subtypes;
}
List<Subtype> subtypes = new ArrayList<Subtype>();
boolean enableSearch;
}
When i load preference domain,user entity loaded also.
I am currently working with 'spring-data-mongo-1.6.3'. And instead of the db reference loading eagerly, it is properly loading with a proxy object. I guess you might want to check once again.
Cheers

Spring Data MongoDB No property get found for type at org.springframework.data.mapping.PropertyPath

I am using Spring Data MongodB 1.4.2.Release version. For Spring Data MongoDB, I have created the custom repository interface and implementation in one location and create custom query function getUsersName(Users users).
However I am still getting below exception:
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property get found for type Users! at org.springframework.data.mapping.PropertyPath. (PropertyPath.java:75) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241) at
org.springframework.data.repository.query.parser.Part.(Part.java:76) at
org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:201) at
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:291) at
org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:271) at
org.springframework.data.repository.query.parser.PartTree.(PartTree.java:80) at
org.springframework.data.mongodb.repository.query.PartTreeMongoQuery.(PartTreeMongoQuery.java:47)
Below is my Spring Data MongoDB structure:
/* Users Domain Object */
#Document(collection = "users")
public class Users {
#Id
private ObjectId id;
#Field ("last_name")
private String last_name;
#Field ("first_name")
private String first_name;
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
}
/* UsersRepository.java main interface */
#Repository
public interface UsersRepository extends MongoRepository<Users,String>, UsersRepositoryCustom {
List findUsersById(String id);
}
/* UsersRepositoryCustom.java custom interface */
#Repository
public interface UsersRepositoryCustom {
List<Users> getUsersName(Users users);
}
/* UsersRepositoryImpl.java custom interface implementation */
#Component
public class UsersRepositoryImpl implements UsersRepositoryCustom {
#Autowired
MongoOperations mongoOperations;
#Override
public List<Users> getUsersName(Users users) {
return mongoOperations.find(
Query.query(Criteria.where("first_name").is(users.getFirst_name()).and("last_name").is(users.getLast_name())), Users.class);
}
/* Mongo Test function inside Spring JUnit Test class calling custom function with main UsersRepository interface */
#Autowired
private UsersRepository usersRepository;
#Test
public void getUsersName() {
Users users = new Users();
users.setFirst_name("James");`enter code here`
users.setLast_name("Oliver");
List<Users> usersDetails = usersRepository.getUsersName(users);
System.out.println("users List" + usersDetails.size());
Assert.assertTrue(usersDetails.size() > 0);
}
The query method declaration in your repository interface is invalid. As clearly stated in the reference documentation, query methods need to start with get…By, read_By, find…By or query…by.
With custom repositories, there shouldn't be a need for method naming conventions as Oliver stated. I have mine working with a method named updateMessageCount
Having said that, I can't see the problem with the code provided here.
I resolved this issue with the help of this post here, where I wasn't naming my Impl class correctly :
No property found for type error when try to create custom repository with Spring Data JPA

POJO information lost during RPC call (GWT)

I am having issues with RPC calls and GWT. Essentially, I have a Person class (common code between client and server) that is created in the client side web code, sent to the server code via an RPC call, and then saved to a DB (OrientDB). I have verified that the following work:
RPC call - I am able to send info to the server and retrieve info from the server
save to DB - have verified that a Person object is saved to the DB
Where I am having issues is the transfer of the POJO from the client to the server. I have verified that the POJO's properties are intact right before it is sent to the server, however, the object passed to the server contains null values for all properties. Essentially, the class is transferred but the information is not. It then saves to the DB, but obviously without any relevant information contained within it.
I will copy what I feel is relevant below, please let me know what else I can provide to make this problem easier to identify. Note these are still in a testing state, so mind the comments :)
Any idea why my POJO's information is being lost in translation?
Person object, followed by the abstract class it inherits from:
public class Person extends org.matesweb.shared.AbsPerson implements Serializable
{
#Id
private String id; // DON'T CREATE GETTER/SETTER FOR IT TO PREVENT THE CHANGING BY THE USER APPLICATION,
// UNLESS IT'S NEEDED
//sets new user details
public void setPerson(String fIrstName, String mIdInit, String lAstName, String email, String password)
{
firstName = fIrstName;
middleInitial = mIdInit;
lastName = lAstName;
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public Object getId()
{
String tmp;
tmp = id.toString();
return tmp;
}
//end class
}
public class AbsPerson implements Serializable
{
String firstName;
String middleInitial;
String lastName;
// public sys.Login login;
public org.matesweb.shared.Group[] groups;
private org.matesweb.shared.Purchase[] purchases;
/*this method adds a new purchase to the purchases variable*/
/* public void addPurchase(float price, String description)
{
people.Purchase newPurchase = new people.Purchase(login, price, description);
}
*/
/*adds a person to a group by comparing the passed in group ID and PWD*/
public void addGroup(String groupID, String groupPWD)
{
//compare group ID with group PWD to add a user to the group
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public String getFirstName()
{
return firstName;
}
public void setFirstName(String name)
{
firstName = name;
}
public String getMiddleInitial()
{
return middleInitial;
}
public void setMiddleInitial(String midInit)
{
middleInitial = midInit;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String ln)
{
lastName = ln;
}
/*
public sys.Login getLogin()
{
return login;
}
public void setLogin(sys.Login log)
{
login = log;
}
*/
public org.matesweb.shared.Group[] getGroups()
{
return groups;
}
public void setGroups(org.matesweb.shared.Group[] gro)
{
groups = gro;
}
public org.matesweb.shared.Purchase[] getPurchases()
{
return purchases;
}
public void setPurchases(org.matesweb.shared.Purchase[] purch)
{
purchases = purch;
}
}
Service
package org.matesweb.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import org.matesweb.shared.Person;
#RemoteServiceRelativePath("peopleService")
public interface PeopleService extends RemoteService {
//test services
String stringTest(String outgoingString);
Person getPerson(String persId);
//production services
String savePerson(Person p);
}
ServiceAsync
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.matesweb.shared.Person;
public interface PeopleServiceAsync
{
//tests
void stringTest(String outgoingString, AsyncCallback<String> incomingString);
void getPerson(String persId, AsyncCallback<Person> retPerson);
//production services
void savePerson(Person p , AsyncCallback<String> st);
}
ServiceImpl call for this particular method:
//production calls
#Override
public String savePerson(Person p) {
String st = ioObj.saveObj(p);
if(st.equals("Success")){
return "Your information has been saved successfully!";
} else{
return "Something has gone wrong on our end... Sorry! Error:<br /> " + st;
}
}
and finally, the call itself
private static void savePerson(Person p)
{
// Initialize the service proxy.
if (peopleSvc == null) {
peopleSvc = GWT.create(PeopleService.class);
}
//resets status
st="";
// Set up the callback object.
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
st = caught.getMessage();
Label stLabel= new Label(st);
personTable.setWidget(3,1,stLabel);
}
#Override
public void onSuccess(String result) {
st = result;
HTML stLabel= new HTML(st);
joinPanel.add(stLabel);
}
};
// Make the call to the people service.
peopleSvc.savePerson(p, callback);
}
I was able to fix this issue by implementing GWT's IsSerializable interface. I also removed the Serializable interface from the Person class and let it inherit IsSerializable from the abstract class it inherits from.

JPAException occur when trying to access to any page after Secure login

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.