So I am creating a chat app for android and I'm using Java and I need some help wrapping my head around some things. Whenever the user first registers, I am creating a new object of a class named User. When they enter the next layout, I need to access that objects data.
public class User {
public String username;
public User() {}
public User(String username) {
this.username = username;
}
public String getUsername(){
return username;
}
}
This is my User class. When they send a message, I need to be able to grab their username from this User object from an entirely different method without passing the object through a parameter. I can't seem to wrap my head around how to access their information and none of my methods seem to work. Any help is appreciated
If you do
User myUser = new User();
the variable myUser contains a reference to the newly created object. You must keep this reference around in order to later access the object. How exactly you do this depends on the logic of your program. Sometimes you would keep it in a field of another object or pass it around as parameter. For example
un = myUser.getUsername();
or
void myMethod(User theUser) {
...
String un = theUser.getUsername();
}
...
// call the method passing the user reference
myMethod(myUser);
in the main class make the data object... static
public static Model obj;
obj= new Model();
then from other class access it with your class name
example
main.obj;
I solved this issue by just using SharedPreferences. I stored the username associated with the key of each user. This way, I can always search the username for each user.
Related
I have a pojo class as follows.
public class Person {
private String name;
private Address address;
public String getName() { ... }
public Address getAddress() { ... } //Address bean
public void setName() { ... }
public void setAddress() { ... }
}
Get data from DB (json converted to above POJO)
Show it to user
User changes his Address
Saving back to DB
This is what currently happening. Now I am trying to make a delta of user made changes Vs database changes. (which is address alone)
I need to know what user has changed. This is for making an audit log.
In this case it's address. That new address should be put into the new Person-POJO class (with all other setters as NULL).
So that I would get
address {
-- new address
},
name {
-- NULL //or no need to have "name" as address only changed
}
What would be the best method to achieve this ?
I know there are few libraries with with we can compare beans with some comparators. But it will just compare, will not provide the changed part alone. If there is any, please provide a link.
I got an idea from https://stackoverflow.com/a/472637/2086966 answer. Trying to do as this method.
My issue is how to organize the code. Let say I have a User class
public class User extends RealmObject {
#PrimaryKey
private String id;
#Required
private String name;
public User() { // per requirement of no args constructor
id = UUID.randomUUID().toString();
}
// Assume getter & setter below...
}
and a Util class is needed to handles the save in an asynchronous manner since RealmObjects cannot have methods other than getter/setter.
public class Util {
public static void save(User user, Realm realm) {
RealmAsyncTask transaction = realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealm(user); // <====== Argument needs to be declared final in parent method's argument!
}
}, null);
}
}
The intention is to put save() in a Util class to prevent spreading similar save code all over the code-base so that every time I wanted to save I would just call it as such:
User u = new User();
u.setName("Uncle Sam");
Util.save(u, Realm.getDefaultInstance());
Not sure if this affects performance at all, but I was just going to save all fields overwriting what was there except for the unique id field every single time.
The problem is that I now need to set the "user" argument as final in the Util.save() method, which means I cannot pass in the object I need to save other than once.
Is there a different way of handling this? Maybe a different pattern? Or am I looking at this all wrong and should go back to SQLite?
Why is it a problem to set public static void save(final User user, Realm realm) ? It just means you cannot reassign the user variable to something else.
That said, the existence of a save() method can be a potential code smell as you then spread the update behaviour across the code base. I would suggest looking into something like the Repository pattern (http://martinfowler.com/eaaCatalog/repository.html) instead.
Realm is actually working on an example showing how you can combine the Model-View-Presenter architecture with a Repository to encapsulate updates which is a good pattern for what you are trying to do here. You can see the code for it here: https://github.com/realm/realm-java/pull/1960
I am using gson to produce json of a collection of objects in Java (Some objects have other collections too). This json will be used to populate the web page for users with different clearance levels. Therefore the detail which users can see differs. Web page only shows what it needs to show however if I use the same json for two different pages then html source code will have more data than it should have. Is there a way to inform gson which variables in which class should be added to the json? As far as I search I could not find an easy way. Either I will produce json myself or clear extra data from the json which gson produced.
I need to use same classes for different clearance levels and get different json.
You are trying to use Gson to generate multiple different JSON outputs of the same objects in the same JVM, which is going to be difficult, both in Gson and any good serialization library, because their express goal is essentially the opposite of what you're looking for.
The right thing to do would be to instead represent these different clearance levels with different classes, and simply serialize those different classes with Gson as normal. This way you separate the security model from the serialization, letting you safely pass this information around.
/**
* Core data class, contains all information the application needs.
* Should never be serialized for display to any end user, no matter their level.
*/
public class GlobalData {
private final String username;
private final String private_data;
private final String secure_data;
}
/** Interface for all data display operations */
public interface DisplayData {
/** Returns a JSON representation of the data to be displayed */
public String toJson();
}
/**
* Class for safe display to an untrusted user, only holds onto public
* data anyone should see.
*/
public class UserDisplayData implements DisplayData {
private final String username;
public UserDisplayData(GlobalData gd) {
username = gd.username;
}
public String toJson() {
return gson.toJson(this);
}
}
/**
* Class for safe display to a trusted user, holds private information but
* does not display secure content (passwords, credit cards, etc.) that even
* admins should not see.
*/
public class AdminDisplayData implements DisplayData {
private final String username;
private final String private_data;
public AdminDisplayData(GlobalData gd) {
username = gd.username;
private_data = gd.private_data;
}
public String toJson() {
// these could be different Gson instances, for instance
// admin might want to see nulls, while users might not.
return gson.toJson(this);
}
}
Now you can sanitize and serialize your data as two separate steps, and use type safety to ensure your GlobalData is never displayed.
public void getDisplayData(GlobalData gd, User user) {
if(user.isAdmin()) {
return new AdminDisplayData(gd);
} else {
return new UserDisplayData(gd);
}
}
public void showData(DisplayData data) {
String json = data.toJson();
// display json however you want
}
If you erroneously tried to call showData(gd) you'd get a clear compilation error that you've done something wrong, and it's a quick fix to get the correct result by calling showData(getDisplayData(gd, user)) which safely and clearly does exactly what you want.
you can add a Expose annotations like this on the filed you don't want:
#Expose(serialize = false, deserialize = false)
private String address;
some more information here:
https://sites.google.com/site/gson/gson-user-guide#TOC-Gson-s-Expose
I have created a server-client chat room style application and I'm trying to transfer a custom object which I have created containing the message and the username of the person using client/server application. To do this I have created a separate class called message which contains two static variables, one called username and one called messageText:
public class message implements Serializable{
static String username = "";
static String messageText = "";
public message(String message, String user){
System.out.println("Setting username and messageText");
username = user;
messageText = message;
}
public message(Object recievedObject){
username = ((message) recievedObject).getUsername();
messageText = ((message) recievedObject).getMessageText();
}
}
I send an object of this class from my server to a client as follows:
message sendMessage = new message(enteredText, "SERVER");
output.writeObject(sendMessage);
It is accepted by the client as follows:
message recievedMessage = (message) input.readObject();
cw.say(recievedMessage.getMessageText(), recievedMessage.getUsername());
However both methods above getMessageText() and getUsername() will return whatever the variable was initialized with on the receiving end, and return the correct values on the sending side.
A few hours of trying to fix this problem has provided no solution, so any help that you guys can give me is very, very appreciated! Thanks.
static fields are not serialized. If you make them non-static it should work
Static variables are shared by all instances of a class. That means it doesn't make much sense to serialize them.
In a message, the fields "username" and "messageText" are likely not meant to be static, unless there is only one message in existence.
I have three java files(Login.java,Sales.java), and i want to pass a variable "Username" to other 3 java files so that the Sales.java can show the "Username"
This is what i done, build a loginstaff.java:
public class LoginStaff {
private String Username;
public void LoginStaff() {
}
public void LoginStaff(String Username) {
this.Username = Username;
}
public String getUsername() {
return this.Username;
}
public void setUserame(String Username) {
this.Username = Username;
}
}
In Login.java
...
String login = tfusername.getText();
LoginStaff loginstaff = new LoginStaff();
loginstaff.setUserame(login);
...
In Sales.java
...
LoginStaff loginstaff = new LoginStaff();
System.out.println(loginstaff.getUsername());
...
The problem is i cannot get the Username in Sales, it returned "null".
I know this is something related to new a object in different class, but i dont know how to fix this.
It's not a matter of where you're calling it - it's a matter of it being two different objects. This would demonstrate the same problem in a single method:
public void showProblem() {
LoginStaff staff1 = new LoginStaff();
// Assume typo in method name is fixed
staff1.setUsername("foo");
LoginStaff staff2 = new LoginStaff();
System.out.println(staff2.getUsername()); // Prints null
}
Two different objects will have two distinct sets of fields - that's deliberate and a good thing. You can't create a new object and expect it to have all the field values that you set on another object.
It sounds like fundamentally the problem is that you need your Sales code to know about the LoginStaff object created in your Login code. Without knowing more about your design, we can't really tell you the best way of achieving that.
If in one class you do this:
LoginStaff loginstaff = new LoginStaff();
loginstaff.setUserame(login);
And in the other class you do this:
LoginStaff loginstaff = new LoginStaff();
loginstaff.getUsername();
You are creating two different objects. Thus, for the second object, the UserName was never set. If you want to access the same object, you will need to reference it. A work around would be to pass a LoginStaff object around when the objects are initialized. This will allow you to access the same settings.
In Sales.java
...
LoginStaff loginstaff = new LoginStaff();
loginstaff.getUsername();
...
Here 1st line creates a new object with default initialization of variables, which is null in case of String type. Before using getUsername(), you have to call setUsername()
Or otherwise create a cunstrocter in Sales.java which accepts the LoginStaff object and after setting the username at Login.java, pass that object to Sales.java and in Sales.java instead of creating a new LoginStaff object, store the object passed by Login.java and then use getUsername()
When you create your sales object, I suggest you provide it with a MainClass(this) parameter. Obviously update your sales constructor to reflect this. This allows you to store an identical MainClass in your sales class, which you can use to query for name or whatever else you may need.
Basically Sales s1 = new Sales(this);
I have had a similar process where I had a UI bar class, but needed to start a method in the main class to act when the user clicked on a button in the UI. The way I did it was had a classwide field at the top of my main class.
so basically:
public class MainClass() {
private InterfaceTab interfaceTab;
//Instantiate the field in the constructor or main method of MainClass, so that way both classes can access each other:
interfaceTab = new InterfaceTab(this);