This might seem like a very basic question, but I have a model (User) which I want to store an ArrayList of Strings (they are the id's of other users). I declare the List like this:
public List<String> friends = new ArrayList<String>();
After I add an entry to the array, I save the user. But friends is always null when I try to use it. Is there a specific way to save an ArrayList? Any help would be appreciated.
My model:
#Entity
public class User extends Model {
#Id
public String username;
public String password;
public List<String> friends = new ArrayList<String>();
public static Finder<String, User> find = new Finder<String, User>(String.class, User.class);
// Constructor
public User(String username, String password){
this.username = username;
this.password = password;
}
// Methods
public void addFriend(String friend){
friends.add(friend);
}
// Static Methods
public static User authenticate(String username, String password){
return find.where().eq("username", username).eq("password", password).findUnique();
}
public static void befriend(String user1, String user2){
User.find.ref(user1).addFriend(user2));
User.find.ref(user2).addFriend(user1);
User.find.ref(user1).save();
User.find.ref(user2).save();
}
}
The controller method:
return ok(index.render(
User.find.byId(request().username()).friends,
));
And a very simple view:
#(friends: List[User])
<div id="current_friends">
#for(friend <- friends) {
#friend.username
}
</div>
You need to save the relations 'manually' with saveManyToManyAssociations(String fieldname), for an example:
public static void befriend(String userName1, String userName2){
User user1 = User.find.byId(userName1);
User user2 = User.find.byId(userName2);
user1.friends.add(user2);
user2.friends.add(user1);
user1.save();
user2.save();
// here...
user1.saveManyToManyAssociations("friends");
user2.saveManyToManyAssociations("friends");
}
(note: written from top of my had so debug it yourself pls)
One potential reason for this problem could be your view:
The first line of your view is
#(friends: List[User])
The User does not have a package name, which could cause the null pointer exception.
In my case, my User bean is under models package, so I have the following line:
#(friends: List[models.User])
I encountered the exact same problem, and here is how I fixed it (with a little explanation coming along).
In fact, you try to save an ArrayList (thus something which size is undefined) in a DataBase. And apparently (and quite logically), the Play Framework doesn't really like it ; you have to use whether annotations or a transient class. I decided to use the class way (also because i don't know how to use the annotations to make a sub table, so I didn't took the risk, but it's not the best way to do it. In fact, it's an horrible way of doing it. But still, here it is).
In your case, you could to this :
#Entity
public class Friends extends Model {
#Id
public Long id;
#Required
public String user1;
#Required
public String user2;
public static Finder<Long, Friends> find = new Finder<Long, Friends>(Long.class, Friends.class);
//Here put your functions, I myself only added an insert method for the moment :
public static void add(String user1, String user2){
Friends f = new Friends();
f.user1 = user1;
f.user2 = user2;
bu.save();
}
}
And in your User model, just change the part in which you save both user into each other's List by this function.
Hope this will help.
Note : the id is here because I like numeric ids, feel free to change it.
Note 2 : Of course, it would be much better to use #ManyToOne and #OneToMany annotations, but as I wrote before, I don't know exactly how does it work.
Related
Hi I'm new to Java and Selenium and I am trying to figure out some things. And please forgive my English.
Let's assume I have 2 or more countries and I only have one "testclass" for logging in.
For Country1 I have the username:"user1" and the password "pass1".
For country2 it is "user2" and "password2". I do not want to hardcode the username and the password into the testclass so I created another one which holds the variable e.g
public static final String iUsername = "user1";
and
public static final String mUsername = "user2";.
In the testclass I would call it e.g
driver.findElement(By.id("username")).sendKeys(Constant.iUsername);.
My Question is how can I select before I start the test the other username (mUsername) without always changing the code at the testclass.
Like I said I'm new and I am not so good at explain things.
Thanks
This is a pseudo-code that shows a possible design for your test:
Create a class for Users:
public class User {
public String username;
public String password;
public Users(String username, String password) {
this.username = username;
this.password = password;
}
}
Create a class to store their information (similar to your static class):
public class UserFixture {
public static User userUSA = new User("userUSA", "passUSA");
public static User userUK = new User("userUK", "passUK");
public static User userChina = new User("userChina", "passChina");
public static User userFrance = new User("userFrance", "passFrance");
}
Create a HashMap with the list of countries you want to test:
public class AccessTest {
List<String> countries = Arrays.asList(
"www.website.com",
"www.website.co.uk",
"www.website.ch",
"www.website.com.fr");
Map<Users, List<String>> userCountries = new HashMap<Users, List<String>>();
userCountries.put(UserFixture.userUSA, countries);
userCountries.put(UserFixture.userUK, countries);
userCountries.put(UserFixture.userChina, countries);
userCountries.put(UserFixture.userFrance, countries);
public static test() {
// u = user; c = country
userCountries.forEach((u, c) ->
c.forEach( country ->
goToUrl(country);
login(u);
// Write the rest of the test below
)
)
}
}
There are many ways to do this, but easiest one is -
You can have one properties file containing your user ids and passwords and one extra parameter (say Choice = 1 or 2) defining which user you want to use. This way you will not need to have the class holding constants. Then you can have one class for reading parameter file. Create a login function where you can pass the login data. Then in your test class you can use ids and their passwords based on the value of Choice.
if(properties.getProperty("Choice") == 1)
{ Login(properties.getProperty("User1Id"),properties.getProperty("Pass1"));
else if (properties.getProperty("Choice") == 2)
{ Login(properties.getProperty("User2Id"),properties.getProperty("Pass2"));
}
else //some error
This way you just have to change the value of choice variable in your properties file.
Consider following model:
public class Contact {
#Required
public String name;
#Valid
public List<Information> informations;
}
public static class Information {
public String securedField;
#Required
public String email;
#Valid
public List<Phone> phones;
public static class Phone {
#Required
#Pattern(value = "[0-9.+]+", message = "A valid phone number is required")
public String number;
}
}
}
I don't want Information securedField to be affected by mass assignment vulnerability. So i decided to set array of allowedFields for Contact Form.
As i know, play forms are based on Spring DataBinder, so is it possible to handle collection fields? I don't want to write smth like:
name
informations[0].email
informations[0].phones*
informations[1].email
informations[1].phones*
etc
Following doesn't work:
name
informations.email
informations.phones*
Should i extend existing Spring DataBinder and Form classes and override bind method in this case?
Here's an arguably simpler solution. How about defining an extra constraint that will trigger a validation failure if the POST data contains any informations[%d].securedField values?
import javax.validation.constraints.Null;
public static class Information {
#Null
public String securedField;
...
}
I think that this way you can call the default bindFromRequest method instead of the one that accepts a whitelist of form field names, and still be protected against a mass assignment attack.
One shortcoming with this approach admittedly is that it would ultimately leak the names of your internal fields in the event of a concerted mass assignment attack. However if they had fairly bland, meaningless names such as securedField (no offence intended!), I'm not sure how this information could be exploited by an attacker.
Edit
If you want to allow assignment to the field based on the current user type, maybe bean validation groups could help:
import javax.validation.constraints.Null;
public class Contact {
public interface Administrator {}
public interface User {}
...
public class Information {
#Null(groups = User.class)
public String securedField;
...
}
}
Controller code
...
final Form<Contact> contactForm;
if (currentUser.isAdministrator()) {
contactForm = form(Contact.class, Administrator.class).bindFromRequest();
} else {
contactForm = form(Contact.class, User.class).bindFromRequest();
}
...
If I understand your question correctly, you can use the following patterns to whitelist nested collection fields:
informations[*].email
informations[*].phones[*].*
i.e.
form.bindFromRequest("name", "informations[*].email", "informations[*].phones[*].*");
I want to make a class that can interact with a database, which has the following desired functionality:
It has a method to return all fields from the database, later can be changed such that it can also limit with it returns.
It has a method to insert a specific instance of this class.
It has a method to update a specific instance of this class.
I will show the code in a moment after further explanation.
Now I want to extract an interface, or rather an abstract class I think might be more appriopiate, to be sure that all classes/datafields follow the same 'interface', and to be able to use them as a supertype in Lists etc.
The data class, in this case Account.java, should represent a table in a database which stores {Username, Password}, I am omitting an explicite unique identifier for now, still not sure if I will make an additional ID field or use the uniqueness of the Username field.
It would be best if the abstract class itself would handle all the MySQL interaction 'mess'.
Account.java so far:
package testthing;
import java.util.Map;
/**
*
* #author Frank
*/
public class Account {
private final static String ALL_QUERY = "SELECT * FROM accounts";
private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";
private String username;
private String password;
public Account(final String username, final String password) {
this.username = username;
this.password= password;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public static Map<String, Account> getAll() {
//return a map using the ALL_QUERY string
}
public void insert() {
//insert this using INSERT_QUERY
}
public void update() {
//update this using UPDATE_QUERY
}
}
I know that I haven't been that clear I'm afraid, but I hope this is enough to help me get going.
Basically I want to always be able to use the followings methods when working with a TableObject, which Account would be a subset of:
Account.getAll();
new Account("test", "test").insert();
currentAccount.setPassword("newPassword"); currentAccount.update();
All the nasty SQL stuff should be hidden inside the proposed abstract class. The only thing you cannot escape in a TableObject class is the definition of the SQL queries.
Regards.
EDIT: In current example Account.getAll() returns a Map<String, Account>, but in reality the first generic argument should be the type of the key in the database. So if you would use an unique ID then it would need to return a Map<Integer, Account>. I hope this change makes it in time for people to read it.
Is it not more logical, to have the connection code and all the "nasty" stuff in the superclass, but simply have a more general method in the superclass, that is used by it's sub classes. For example:
public void executeUpdate(String query)
{
// Code to execute update.
}
public Map<String, Data> getData(String query)
{
// Code to get data.
return data;
}
This way, these methods are more general. It means that you can implement several classes that simply pass query data, rather than constantly having to update a superclass every single time you want to add new functionality.
Obviously I've just assumed a type Data here, but that might be something to look into. The aim here is to decouple your classes as much as possible. This means you can add as many new classes as you want, and they can use their supertype without hinderence.
This also means things like
Account.getAll();
is a little less complicated, because if you have getAll in your superclass, where is the reference that you want to get all accounts? If the code is actually in the Account class, you can customize the query, and send it off to the getData method to be executed.
Let's say I have a method in java, which looks up a user in a database and returns their address and the team they are on.
I want to return both values from the method, and don't want to split the method in two because it involves a database call and splitting involves twice the number of calls.
Given typical concerns in a moderate to large software project, what's the best option?
whatGoesHere getUserInfo(String name) {
// query the DB
}
I know the question smells of duplication with existing ones, but each other question had some element that made it different enough from this example that I thought it was worth asking again.
you have some options.
The most OOP it will be create a class to encapsulate those 2 properties, something like that
private class UserInfo {
private Address address;
private Team team;
}
Or if you want a simple solution you can return an array of objects:
Object[] getUserInfo(String name) {
// query the DB
return new Object[]{address,team};
}
Or if you want to expose this method to some library you can have some interface that it will consume those properties, something like this:
class APIClass{
interface UserInfo{
public Address getAddress();
public Team getTeam();
}
UserInfo getUserInfo(String name) {
// query the DB
return new UserInfo(){
public Address getAddress(){ return address; }
public Team getTeam(){ return team; }
};
}
}
cant a map help , A MultivalueMap. Where the key is the user name and the 2 values are the adress and the team name. I am assuming both your Address and team are String variables, You can know more about Multivalue Map here
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/MultiValueMap.html
http://apachecommonstipsandtricks.blogspot.in/2009/01/multi-value-map-values-are-list.html
First model your abstractions, relationships and multiplicity well (see an e.g. below). Then you can model tables accordingly. Once these two steps are performed you can either leverage JPA that can be configured to load your object graph or you write JDBC code and create the graph your self by running a SQL query with proper SQL JOINs.
A User has an Address
A Team can have 1 or more Users (and can a User play for more teams?)
You can return a String array with user name and group name in it . The method looks like :
public String[] getUserInfo(String name) {
String[] result = new String[2];
// query the DB
...
result[0] = userName;
result[1] = groupName;
return result;
}
A common solution to this kind of issue is to create a custom object with as many attributes as the values you want to return.
If you can't create a new class for this, you can use a Map<String, Object>, but this approach is not type-safe.
I thought Guava had a generic Pair class already, but I cannot find it. You can build your own using generics if you're on Java 1.5+.
public class Pair<X,Y>
{
public final X first;
public final Y second;
public Pair(X first, Y second) {
this.first = first;
this.second = second;
}
}
Feel free to make the fields private and add getters. :) Using it is easy:
return new Pair<Address,Team>(address, team);
Update
Apache Commons Lang has Pair. See this SO question for more options.
My goal here is get an object that I can iterate over and grab my User's firstName and his favColor.
I have this:
for (Map user : userListing){
String firstName = (String) user.get(User.FIRST_NAME);
String favColor = (String) user.get(User.FAVORITE_COLOR);
// Build up some Arrayish object add "Bob", "red"
//
// what do i do here?
}
I'm unsure if I need to create, say an Array of Arrays?
My thought is that way I know the outer level of the Array is representative of each User, then once I'm the next level deep, item[0] would be the first name and item[1] would be the color.
I'm not sure what would be the best solution here. Using a Map to represent an user is already wrong in first place. I'd create a javabean class which represents an User.
public class User {
private String firstName;
private String favoriteColor;
public String getFirstName() {
return firstName;
}
public String getFavoriteColor() {
return favoriteColor;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setFavoriteColor(String favoriteColor) {
this.favoriteColor = favoriteColor;
}
// Add if necessary other javabean boilerplate like Serializable,
// default c'tor, full c'tor, equals(), hashCode(), toString().
}
Then just collect them in a List<User> and pass that around instead.
Two ways to do it that are pretty simple
Map<String,Map<String,Double>> map2d = new HashMap<String,Map<String,Double>>();
For each new "x-coordinate", you'd have to instantiate
a new sub-HashMap, and put it into map2d. This could all be
wrapped in some new class.
to retrieve an element, you just use:
map2d.get(xKey).get(yKey)
Create a pair type and use that as your map key
http://www.velocityreviews.com/forums/t390520-2d-lookup-table.html
I would recommend:
create a java bean like object:
class Preferences{
//properties
//getters
//setters
}
then have a array of Preferences
Preferences[] userPrefs = new Preferences[N]
iterate by for (Preferences p : userPrefs) { //do the stuff}