Displaying various objects' instance variables in a JTable and modifying them - java

I am designing an application that has two widgets:
-A list that contains arbitrary objects
-A table that displays specific properties of the currently selected object
The goal is to be able to pick an object from the list, look at the properties, and modify them as necessary. The list can hold objects of various types.
So say the list contains Vehicle objects and Person objects
public class Person
{
public String name;
public Integer age;
}
public class Vehicle
{
public String make;
public String model;
}
If I click on a Person object, the table will display the name and age, and I can assign new values to them. Similarly, if I click on a Vehicle object, it will display the make and model in the table and allow me to modify them.
I have considered writing a method like
public String[] getFields()
{
return new String[] {"name", "age"};
}
Which returns a list of strings that represent the instance variables I want to look at, and use some reflection methods to get/set them. I can define this getFields method in all of the classes so that I can use the table to handle arbitrary objects that might be thrown into the list.
But is there a way to design this so that I don't resort to reflection? The current approach seems like bad design.
On the other hand, I could create multiple TableModel objects, one for every possible class. The table would know what rows to display and how to access the object's instance variables. But then everytime a new class is added I would have to define a new table model, which also sounds like a weak design.

You have a class (Vehicle) and you know the names of some properties (make, model) that you want to be able to manipulate dynamically for an instance of this class through a JTable UI.
You have various different approaches to chose from.
A. Use the reflection API
This is what the reflection API is made for. If you want something so dynamic, there is nothing wrong with using reflection. The performance overhead will not be significant for this use case.
B. Use a library like beanutils that is based on the reflection API
This should be easier than directly using the reflection API, but it has the drawback that you need to include another dependency in your project.
C. Create dynamically at runtime the different TableModel classes.
You can do this using either the java compiler API or javassist. Based on information available at runtime, you are able to compile a new class for each different type of table model. If you follow this approach you must be aware that the creation of the class is a heavy task, so the first time you create a TableModel the application will take some time to respond.
What to chose?
Of course this is your decision. For the specific use case, the overhead added by reflection or beanutils is insignificant, so probably it is better to chose between A or B. In another use case where performance is more critical, then you could examine the C approach, without forgetting the class creation response time problem.
EDIT:
I just realized that in this specific use case there is another important functionality required. Convert from String to the appropriate data type of each property and vice cersa. Beanutils has perfect support for that, so it gets a plus here.

Related

How to associate an object with the quantity of that object

I am working on a Java application and came across a general implementation/meta question and wanted to reach out for suggestions.
I am looking to associate a Java object with a quantity. The java object is complex. In my case, it is a serializable object that represents JSON data from a 3rd party API. I am looking to associate a quantity with this complex Java object.
As this may be something that is easier to understand with an example, here is one. Say I have a Car class that is used to represent a car. It contains all the details of what make a car a car and is a general form that can be used to communicate over an API. Say I am making an inventory app for a dealership. The dealership would want to know how many of each Car they have. Hence the need for the association.
Ideas
There are some ways I can think of the do this.
Class it out
One idea would be to create classes that capture this association. One could have an InventoryEntry class that contains a Car and a quantity. Your dealerships inventory would then consist of a List of InventoryEntry objects.
Arrays
One can also implement this association via an Array mechanism. This can be done by creating an ArrayList<Car> for the cars and an ArrayList<Integer> for the quantity. The index for each list would be used to associate the two.
Would you recommend one of these method or some other implementation?
Using ArrayList makes it a little bit easier to start out, but if you are going to maintaining and extending this application, creating a custom class will save you a lot of time in the long run. The reason is that it would be difficult to change the ArrayList class. Yes, you could subclass the arraylist class, and override the methods that you need to, but that is making more work for yourself.
For the basic scenario that you gave, creating a CarInventory class could be extended for new behavior. The new class could just wrap a basic ArrayList or HashMap implementation, but being able to extend your application for long term maintainability is important.

Passing arguments to java function in bulk

What would you use if you wanted to pass a list of options into a function?
For example, if you have an interface to a server:
public interface Server {
public void authUser(String username, String password, <xyz> options);
}
What structure would use use for to pass a set of options? Something like a HashMap?
The reason I'm saying that it comes from tunnel vision is because I feel that this goes against Java standards. Java has method overloading. So if I get flames for raising the question I understand. But overall, maybe in different cases, would you ever pass bulk data in some collection and, if yes, which one?
Option1 : If you are choosing any collections like List or Set these are specific to an object . I mean,
Lets Assume, Set sets = new HashSet();
If I want 5 Object of different different class having no relationship to be send, then It would be very difficult to recognize that which Object is belong to which class while Iteration. So, I wont recommend Collections.
Option2 : If you are choosing Map, the same above problem may occurs while getting the Object Dynamically. So, This Options is also not recommended.
Option3 :
Why cann't you create your own DTO and in that DTO place your reqyired datastructure and pass it over.
If you want 5 different Object to be pass then, you can pass. If all are of same type then you may use Collection or array or Variable Arguement based on your scenerio.
I think anything Serializable is exactly the thing. If you can serialize the object, then you can pass (store, transmit...) it, passing it's properties in bulk. What format of serialized data to choose, is another question.
It depends on the data you want to pass.
You can use a map(hashmap) if you are passing key-value pairs.
If it is just a list of diffrent object, you can use List(ArrayList)
Other option is to create DTO(data transfer object) with getter and setter methods.
You may want to take a look at VARARGS feature that was introduced in JAVA5.
I'd suggest a Map [HashMap] as you can then access the argument values via their Keys.

How to add java custom or string object to DAO model object at runtime?

I need to add new String object to Array of custom type object, ServiceOrderEntity in this case. I know that this kind of breaks ServiceOrderEntity integrity but I have to access this field from jsp. What is the best way to do it?
DAO class:
...
SQLQuery localSQLQuery = localSession.createSQLQuery(query).addEntity(ServiceOrderEntity.class);
localList = localSQLQuery.list();
Iterator itr = localList.iterator();
while (itr.hasNext()){
String field = "some value";
itr.next().append( field ); // something like that maybe....
}
return to Service class
...
Service class
...
List list = perform DAO request
model.addAttribute("serviceOrderList", localList);
....
UPDATE
I have all models generated by Hibernate and I don't want to touch them. I need to add to custom object, in this case ServiceOrderEntity or find workaround. I think I can make copy of it and append new field to it (using Dozer)? New fields is result of other complex subqueries.
List of ServiceOrderEntity objects at runtime:
-list
--[0]model.ServiceOrderEntity#d826d3c7
---createdBy = {....}
---serviceRequestFK{java.Lang.Integer} // << this one
--[1]
....
etc
I need to get name using serviceRequestFK in ServiceOrderEntity. As long as java doesn't allow hot fix (to add custom filed to already created object) I need to find a way to pass to JSP the name field as well. What is the right way?
I really don't want to include DAO mathod requests from jsp...
Create separate list of names?...
Since Java does not allow mix-ins (aka monkey-patching) you'll have to:
Add the field to the base entity.
Return a sub-class that includes this field.
If you'd like to add the field so that the Service class can do its job, then fair enough. However, if the new field is part of the payload in/out then consider instead for that particular service then consider:
Making use-case specific payloads for each service call.
Map the results of these onto your reusable object model. (You can use something like Dozer for this).
The rationale behind this suggestion is to follow the principles of contract-first development.
Your model will be more general purpose, and thus reusable. You can add reusable behaviors to your model classes. Your services will use these behaviors to orchestrate process. (As opposed to having 'anaemic' entitites).
Your service payloads can remain relatively stable over time. So changes to your model won't effect all of your service subscribers. (aka "don't spill your guts").

How to store configuration/property data in a nice way?

Say, we have a superclass Car and two subclasses Ford and Porsche. Now an graphical user interface should display a proper representation (e.g. the name of the Car). We could add an additional method getCarName() to each subclass.
But now, we have another GUI which wants to represent the cars by some other property, e.g. the car name plus production country. We then have to add another method, and so on.
Generally spoken, I want to store some kind of configuration/property in a nice way. The original data structure (with perhaps a lot of subclasses) should not be changed each time another representation is wanted. So I thought of creating a HashMap which associates the subclasses to its property and hand this HashMap to the GUI.
But what kind of key should be used ? HashMap<Car, String> is no solution because I do not want to create objects of cars just to store the representation. The String representation is independent of an instance.
Desing patterns are welcome, too.
You can store all the properties/attributes of any car in a POJO(eg: CarPropertyPOJO) and then use this POJO to display which ever attributes you need. This could be uniformly used across you different pages. As per your question CarPropertyPOJO would contain 2 member variable carName and productionCountry.
In a case you just want to display a property of a single car then just passing a CarPropertyPOJO object to UI would solve the problem.
And suppose you wanna display properties of many cars in a tabular form then you can pass a
Collection object (ArrayList<CarPropertyPOJO> or a HashMap). CarSubClassName could just signify the subClass of the car.
To have a clean design, I would rather prefer to have a method like getProductionCountries in the Car class and that can be overridden by each subclass. When you add a new car, you do need to write more code, but that is rather unavoidable.

NoSQL Schemaless data and statically typed language

One of the key benefits of NoSQL data stores like MongoDB is that they're schemaless. With dynamically typed languages this seem to be a natural fit. You can receive some arbitrary JSON inputs, perform business logic on the known fields, and persist the whole thing without first having to define the object.
What if your choice of language is limited to the statically typed, say Java? How could I achieve the same level of flexibility?
A typical data flow like the following:
JSON Input
Serialize to Java Object to perform business logic
Deserialize into BSON to persist in Mongo
where the serialization to object step is necessary since you want to perform business logic with POJOs, not JSON strings. However, before I can serialize the input into objects, I must define it first. What if the input contains additional fields undefined in the object? While they may not be used in the business logic, I may still want to be able to persist them. I have seem implementations where the undefined fields are put into a map, but am not sure if that's the best approach. For one, the undefined fields may be complex objects as well.
Schemaless data doesn't necessarily mean structureless data; the fields are typically known in advance and some type-safe pattern can be applied on top of it to avoid the Magic Container anti-pattern But this is not always the case. Sometimes keys are entered by the user and cannot be known in advance.
I've used the Role Object Pattern several times to give coherence to a dynamic structure. I think it is well suited here for both cases.
The Role Object Pattern defines a way to access different views of an object. The canonical example being a User that can assume several roles such as Customer, Vendor, and Seller. Each of these views has different operations it can perform and can be accessed from any of the other views. Common fields are typically available at the interface level (especially userId(), or in your case toJson()).
Here's an example of using the pattern:
public void displayPage(User user) {
display(user.getName());
if (user.hasView(Customer.class))
displayShoppingCart(user.getView(Customer.class);
if (user.hasView(Seller.class))
displayProducts(user.getView(Seller.class));
}
In the case of data with a known structure, you can have several views bringing different sets of keys into cohesive units. These different views can read the json data on construction.
In the case of data with a dynamic structure, an authoritative RawDataView can have the data in it's dynamic form (ie. a Magic Container like a HashMap<String, Object>). This can be used to query the dynamic data. At the same time, type-safe wrappers can be created lazily and can delegate to the RawDataView to assist in program readability/maintainability:
public class Customer implements User {
private final RawDataView data;
public CustomerView(UserView source) {
this.data = source.getView(RawDataView.class);
}
// All User views must specify this
#Override
public long id() {
return data.getId();
}
#Override
public <T extends UserView> T getView(Class<T> view) {
// construct or look up view
}
#Override
public Json toJson() {
return data.toJson();
}
//
// Specific to Customer
//
public List<Item> shoppingCart() {
List<Item> items = (List<Item>) data.getValue("items", List.class);
}
// etc....
}
I've had success with both of these approaches. Here are some extra pointers that I've discovered along the way:
Have a static structure structure to your data as much as possible. This makes things a lot easier to maintain. I had to break this rule and use the RawDataView approach when working on a legacy system. You may also have to break it with dynamically-entered user data as mentioned above. In which case, use a convention for non-dynamic field names such as a leading underscore (_userId)
Have equals() and hashcode() implemented such that user.getView(A.class).equals(user.getView(B.class)) is always true for the same user.
Have a UserCore class that does all the heavy lifting of common code such as creating views; performing common operations (like toJson()) returning common fields (like userId()); and implementing equals() and hashcode(). Have all views delegate to this core object
Have an AbstractUserView that delegates to the UserCore and implements equals() and hashcode()
Use a type-safe heterogeneous container (like ClassToInstanceMap) constructing/caching views.
Allow the existence of a view to be queried. This can be done with either a hasView() method or by having getView return Optional<T>
You can always have a class which provides both:
easy access to attributes you know about and optional fallback cases to older formats (for example it can return "name" if it exists, or older case of "name.first" + "name.last" if it doesn't (or some similar scenario))
easy access to unknown elements simulating the map interface
Whether you do a full validation or not, whether you allow extra undefined attributes or not depends on what you want to achieve. But I think that creating an abstraction which allows you either way of accessing the data is the best solution.
Hopefully over time, you'll get to the stage where your schema is pretty much stable and messing directly with the attributes is not needed anymore.
This is not well solved in Java due to the lack of dynamic types. One way this can be solved is using Maps.
Map
The object can again be a Map of objects.
This is not an elegant way but works in Java. An example : SnakeYaml library for YAML allows traversal in this way.

Categories