public class Model {
public void updateEvent(String name, Date date,String start, String venue, String details,
String opportunity, String more, String end, String row) {
//do stuff here
}
public class Controller {
public void someMethod() {
if(button==view.saveButton) {
model.updateEvent(view.txtEventName.......);
} }
}
public class View {
public JTextField txtEventName;
//10 more consisting of textarea, datechooser, etc
}
How can I pass a bunch of parameters to for Controller to pass to Model to update its state. Well, if the View is acting as form, it will have lots of text fields, text area etc. for data entry. rather than dealing with them individually how can controller gain access to all of them easily to pass to model. I dont want to simply keep adding view.txtWhere.getText() which is long.
Create an "Event" class that has String name, Date date,String start, String venue, String details,
String opportunity, String more, String end, String row and use it instead ?
Related
Beginner question here. I'm writing a Java program that queries a public API on the internet to retrieve details of discussions on a forum. The data comes back as JSON and I'm parsing that into Java objects to be used in my program.
A discussion normally contains five attributes, i.e. the five public variables. However, in response to a limited number of specific search types, the number of comments is not returned.
Is there a 'best' (in terms of object oriented programming) way to deal with this sort of scenario? My first attempt is below, where I have simply written two constructors, one that assigns a value to numberOfComments, and one that does not.
This doesn't seem like a great solution - what happens if another class creates a DiscussionDetails object, uses the constructor that does not populate numberOfComments, but then later tries to use the numberOfComments field?
I thought that maybe it should be split into two classes, where DiscussionDetails has no numberOfComments field, and DiscussionDetailsSpecialised is a subclass with an additional numberOfComments field. This feels a bit like overkill to me, for the sake of one single field.
Or maybe there's a convention that such a variable is initialised with a particular value like 'false' or '-1' or something?
Are there other, better approaches that an experienced programmer would use for this kind of situation?
I know the example is trivial, but I'm using it to try to illustrate my question as simply as possible.
/**
* Wrapper for a set of JSON data returned from an API
*/
public class DiscussionDetails
{
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
/**
* Constructor that populates all fields
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL, String submittedDate, String numberOfComments)
{
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
this.numberOfComments = numberOfComments;
}
/**
* Constructor method to use when the number of comments is unknown, which happens in certain specific cases
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL, String submittedDate)
{
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
}
}
This has been traditionally solved with "special" values (values that obviously make no sense, eg: -1 for a count) or null (which in a sense is the most special value).
The "best" way to deal with this is, IMHO, java.util.Optional: clients have to check if a value is present when they wish to use it and Optional makes this explicit, avoiding the common source of bugs of a client forgetting to check.
One way to solve this is with a builder. Your example is good, but a builder can help make it more obvious what's going on.
/**
* Wrapper for a set of JSON data returned from an API
*/
public class DiscussionDetails
{
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
public static class Builder{
private DiscussionDetails dd = new DiscussionDetails();
public discussionID(String discussionID) {
dd.discussionID = discussionID;
return this;
}
public discussionName(String discussionName) {
dd.discussionName= discussionName;
return this;
}
public discussionURL(String discussionURL) {
dd.discussionURL= discussionURL;
return this;
}
public submittedDate(String submittedDate) {
dd.submittedDate= submittedDate;
return this;
}
public numberOfComments(String numberOfComments) {
dd.numberOfComments= numberOfComments;
return this;
}
public DiscussionDetails build() {
return dd;
}
}
}
This can make your instantiation a little cleaner, especially with optional fields or a lot of fields.
You would use this like:
DiscussionDetails details =
new DiscussionDetails.Builder()
.discussionID("1")
.discussionName("Name")
.build();
In this particular case, I've set 2 of the fields. The other fields would be null, or the default value. With some extra code, this gives you a lot of flexibility and arguably makes the code easier to read.
If you need to enforce certain fields being set, you can add more methods in the Builder class itself, or throw an error from the build method.
The "special" value for handling a case when there is no value for a given property is a null value (nil in some languages). However, you should document this in your code so that the client of the code knows that the numberOfComments can be null - forgetting about it and trying to use the value ends with one of the most common exceptions - NullPointerException.
call this in your constructor
public class DiscussionDetails {
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
/**
* Constructor that populates all fields
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL,
String submittedDate, String numberOfComments) {
this(discussionID, discussionName, discussionURL, submittedDate);
this.numberOfComments = numberOfComments;
}
/**
* Constructor method to use when the number of comments is unknown, which happens in certain
* specific cases
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL,
String submittedDate) {
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
}
}
I initialize a Password object and I am having trouble using the same object as a string for later purposes like counting the amount of letters in the string. I know that I'm only getting the textual representation of the object with the methods String.valueOf and .toString. How do I go about taking the my object pass and getting the "hello" string I initialized it with?
public class Password {
public Password (String text) {
}
public String getText(){
String string = String.valueOf(this);
return string;
}
public static void main (String[] args) {
Password pass = new Password ("hello");
System.out.println(pass.toString());
}
}
Your actual getText() method doesn't make sense :
public String getText(){
String string = String.valueOf(this);
return string;
}
You try to recreate a String from the toString() method of the Password instance.
It is really not necessary (useless computation) and it is clumsy as toString() is not designed to provide a functional data.
To reach your goal, it is very basic.
Store the text in a field of the Password instance :
public Password (String text) {
this.text = text;
}
And provide a view on the text field.
You could replace getText() in this way :
public String getText(){
return text;
}
Use fields.
public class Password {
private String text; // This is a member (field) It belongs to each
// Password instance you create.
public Password(String value) {
this.text = value; // Copy the reference to the text to the field
// 'text'
}
}
The problem with String.valueOf(this), where this is a Password instance, is that the valueOf() method has absolutely no idea of how to convert a Password instance to a field. You named it "Password", but it could also beMyTextorMySecret. So you need to tell how aPasswordinstance can be displayed as text. In your case, you'll need to just use thetext` field from the abovementioned example.
You should definitely read the docs about classes. I think you're missing something basic.
Note: You should also never store a password into a String, because of security implications, but that's a whole other story, and beyond the scope of your question.
As the title says....
I want to build a POJO with four field variables and at certain runtime events create an instance of this POJO with access to possibly maybe two or three of the fields.
public class Category implements Serializable {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Lets say I create a new Category object but I only want to be able to have access to the name field during runtime. Is there a design pattern I can use to achieve this? I thought about the strategy pattern and looked at the builder but I am still confused if I can do this in java.
Basically the overall goal is to grab an object from a database and return it as a JSON response in jax rs. But sometimes I dont want a complete object returned but only lets say halve of the object to be accessible at during certain runtime events. My apologies if this seems like a dumb question but I know what I want to do but just don't know the best way.
I have the same problem with you, and my project was used springmvc,and the json tool is jackson.With the problem solved, I just use #JsonIgnore.For more details,just read jackson-how-to-prevent-field-serialization
So someone correct me if I am wrong or see a better option than this...with alot of objects this can be alot of extra code for serialization and deserialization...Jackson Provisions is what I need. I can use the annotation #JsonView(DummyClass.class) on the field variable. I will accept this a the best answer in a day or two unless someone else posts a better response.
// View definitions:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
public class Bean {
// Name is public
#JsonView(Views.Public.class) String name;
// Address semi-public
#JsonView(Views.ExtendPublic.class) Address address;
// SSN only for internal usage
#JsonView(Views.Internal.class) SocialSecNumber ssn;
}
With such view definitions, serialization would be done like so:
// short-cut:
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
// or fully exploded:
objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
// (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
objectMapper.writeValue(out, beanInstance); // will use active view set via Config
// or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
This information was pulled from http://wiki.fasterxml.com/JacksonJsonViews
with jackson 2.3, I can do this with JAX-RS
public class Resource {
#JsonView(Views.Public.class)
#GET
#Produces(MediaType.APPLICATION_JSON )
public List<Object> getElements() {
...
return someResultList;
}
}
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.
We have two systems: external and internal, which are sharing information in JSON format (GSON library).
Information from an external system comes in internal and processed here.
Everything was very good, coming from an external system data in JSON format in the internal system data deserialize and processed. For example:
come string:
{UserLogInEvent:{userName:'Name', time:'00.00.00'}}
this string deserialize in object of this class:
UserLogInEvent implement Event {
private String userName;
private Date time;
public UserLogInEvent (String userName, Date time)
{
this.userName = userName;
this.time = time;
}
private UserLogInEvent()
{
this.userName = null;
this.time = null;
}
public String getUserName()
{
return this.userName;
}
public Date time()
{
return this.time;
}
}
or other example:
{UserModifyFile: {userName:'Name',fileName: 'index.txt' time:'00.00.00'}}
UserModifyEvent implement Event {
private String userName;
private String fileName;
private Date time;
public UserLogInEvent (String userName, String fileName, Date time)
{
this.userName = userName;
this.fileName = fileName;
this.time = time;
}
private UserLogInEvent()
{
this.userName = null;
this.fileName = null;
this.time = null;
}
public String getUserName()
{
return this.userName;
}
public Date time()
{
return this.time;
}
public String getFileName ()
{
return this.fileName;
}
}
The algorithm is very simple:
string -> deserialization -> object events created.
But .. further problems began. These problems I can not decide ..
Added new events.
Information that comes with an external system does not contain all necessary data about the event, for example:
{UpdateProductInfoEvent: {userName:'name', time: '00.00.00', product: {id:'123', name: '???', type: '???', cost:'???'}}}
As you can see, the line does not contain all the data ... just deserialized not give a desired result ...
To do this, I still need to call a method that will receive information about a product by its Id.
The algorithm is as follows:
JSON string -> processing line -> product information from ID -> object creation * Event.
The following example:
{ModifyProductCatalogEvent:{userName: 'Name', time: '00.00.00', catalog:{id:'321', catalogType:'???', catalogName: '????'}}}
Again I not have all info about catalog...
So, I ask for help, how do I properly construct an algorithm to create objects in case of lack of data?
You can write your own serialization and deserialization methods by overwriting:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
which enables you to handle those cases yourself. You can still use the default methods by using out.defaultWriteObject/in.defaultReadObject to only have to handle the cases where data may be missing (or if you have default values for invalid objects, read all fields with the normal methods and then overwrite the invalid fields with the correct data).
The first question that I would ask is if the code is throwing exceptions? If not, then inspect the object and set the properties/objects to a defaulted state since there is not way to retrieve the data if they did not send it. Or in the constructor of the objects, add initialization code so that the deserializer will have an initialized object to work with.