I'm using Jodd DbOom to manage my queries and it's really awesome. But right now I'm are facing an undocumented situation.
I have a query that returns a list of objects(A), and each A has a list of objects (B), and each B is joined with other objects(C, D, E, etc). The problem is that the class JoinHintResolver doesn't set the values C, D, E on the B objects. The B objects are set correctly on the A objects.
Below is a test method to reproduce the error. The other used classes(Girl, BadBoy) are from Jodd test packages.
public void testHintsList() {
Room room = new Room();
Girl girl = new Girl();
BadBoy badBoy = new BadBoy();
Object[] data = new Object[] { room, badBoy, girl };
JoinHintResolver jhr = new JoinHintResolver();
Object[] result = jhr.join(data, "room, room.boys, room.boys.girl");
assertEquals(1, result.length);
assertTrue(result[0] instanceof Room);
room = (Room) result[0];
badBoy = room.getBoys().get(0);
assertEquals(girl, badBoy.girl);
}
public class Room {
private Long id;
private List<BadBoy> boys;
public Room() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<BadBoy> getBoys() {
return boys;
}
public void setBoys(List<BadBoy> boys) {
this.boys = boys;
}
}
The documentation doesn't have any example like this, and Google neither. So I don't know if I did something wrong, or if Jodd wasn't prepared for this situation.
How could I set the hints so that Jodd would set the values correctly?
So the problem here is the fact that you have a collection of BadBoys in your Room. And the hint:
room.boys.girl
suggest they you want to inject a Girl instance into a collection. In java words, this is equivalent to:
getRoom().getBoys().setGirl(girl);
Obviously, since getBoys() returns a List, we can not set the girl property.
To test this what I've said, use the following hint instead:
room.boys[0].girl
This would inject the girl instance into the very first element of the list. Or, you can change your Room to have just a Boy property, instead of the list, and the original hint will work.
I hope this works for you :)
(see test)
EDIT
In this branch I have something that looks like a fix :) Now you can write something like:
select $C{room.*}, $C{room.boys:boy.*}, $C{room.boys.girl:girl.*}
from $T{Room room} join $T{Boy4 boy} on $room.id=$boy.roomId
join $T{Girl4 girl} on $boy.id=$girl.boyId
order by $room.id, $boy.id
And you can have the following model:
Room has list of Boy. Each Boy has one Girl assigned. When entityAware is on, this should work. Maybe you have time to test the branch?
Related
I know how to make a collection unmodifiable in java but I dont understand the need for such a method to exist. Can someone please explain this with an example scenario where I would want to make my collection unmodifiable?
Thanks in advance
The most efficient way to share private data outside of a class is to simply return it. But then something outside of the class can change the data that the class depends on. Another option is to copy the data before you share. This takes time and memory to do. Unmodifiable collections will often wrap the data and simply present it without allowing an outside class to edit it. This is faster than making a copy. An outside class can optionally make a modifiable copy if it needs.
An unmodifiable collection is basically read-only which is exactly what you want in case you need to publish such collection to client code and you don't want the client code to modify the collection.
It also promotes immutability which is generally a good thing since you won't have to care about the state of the collection for the rest of the execution of your program. See item 15 of Effective Java (2nd Edition) : Minimize mutability, and to quote Joshua Bloch :
Immutable objects are simple. An immutable object can be in exactly
one state, the state in which it was created.
Note that an unmodifiable collection will not make the contained objects immutable. This is a property each of the contained objects needs to make sure of, if it is required of course.
Take a look at this scenario. There is an application that creates 2 users, and then wants to notify them about something. But only users with name different from Peter should get the notification.
So we have to User.class:
public class User {
private String name;
private Integer id;
public User(final Integer id, final String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public Integer getId() {
return id;
}
}
The users are stored in special holder class (containing map):
public class UsersHolder {
private static Map<Integer, User> usersMap = new HashMap<Integer, User>();
public static void addUser(final User user) {
usersMap.put(user.getId(), user);
}
public static Map<Integer, User> getUsersMap() {
return usersMap;
//return Collections.unmodifiableMap(usersMap);
}
}
Then we have the UsersCreator that creates those users and stores them in a map:
public class UsersCreator {
public static void createUsers() {
UsersHolder.addUser(new User(1, "Peter"));
System.out.println("Created user " + UsersHolder.getUsersMap().get(1).getName());
UsersHolder.addUser(new User(2, "Paul"));
System.out.println("Created user " + UsersHolder.getUsersMap().get(2).getName());
}
public static void main(String[] args) {
UsersCreator.createUsers();
System.out.println("Number of users before notification: " + UsersHolder.getUsersMap().size());
new UsersNotificator().notifyAllUsersButPeters(UsersHolder.getUsersMap());
System.out.println("Number of users after notification: " + UsersHolder.getUsersMap().size());
}
}
And the notificator that notifies all but Peters:
public class UsersNotificator {
public void notifyAllUsersButPeters(final Map<Integer, User> map) {
//we don't need peters, so we'll remove them from the list;
Iterator<Entry<Integer, User>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getValue().getName().equals("Peter")) {
iterator.remove();
}
}
//now we can notify all from the list;
notifyUsers(UsersHolder.getUsersMap());
}
private void notifyUsers(Map<Integer, User> map) {
for (final User user : map.values())
System.out.println("notifyingUsers: " + user.getName());
}
}
Now - the notificator was presented with a map and it may modify it, which it does. It doesn't know that it shouldn't modify it as it's global usersMap. In effect it removes all users with name Peter. It does it for it's own purposes, but the results will be visible for every other class using UsersHolder.
The result is as follows:
Created user Peter
Created user Paul
Number of users before notification: 2
notifyingUsers: Paul
Number of users after notification: 1
When returning unmodifiableMap in UsersHolder the removal will not be possible. The only way would be to create new map with users to notify, so our usersHolder is safe.
This example is a bit big, sorry for that, i failed to think of/create somehting shorter.
Unmodifiable map helps to keep your classes Immutable which is safe(as presented in the example) especially in multithreaded enviroment.
There are many situations in which you do not want your collection to be modifiable. Whenever you know that the collection is initialized with exactly the content it should contain at all times, it can provide security to make it unmodifiable.
The (rather long) example provided by another user is a good example of where it often causes problems. Whenever you traverse a collection, there is a risk you change the collection if you forget to do it on a copy. Making the collection unmodifiable catches and prevents this easy to make mistake.
I'm trying to develop an online hotel booking system. I have the main class which takes input from the user such as their name, their payment information, and other data fields and makes a Reservation object using that information. I have another class called Room that has a list of Reservations for each Room object. The problem I am having is I can't figure out a way to add the Reservation object into the list in the Room object. Here is some of the code:
public class HotelReservationSystem
{
private Reservation reservation;
public void makeReservation(int checkIn, int checkOut)//Other parameters
{
reservation = new Reservation(checkIn, checkOut);
}
}
public class Room
{
private ArrayList<Reservation> reservations;
public void addReservation(//parameters?)
{
reservations.add(//parameter?);
}
}
I don't know how to get the new Reservation object to be passed as a parameter for the add method in the Room class.
I just can't wrap my head around it and was hoping for someone to help jog my thinking process.
Thanks for your help.
Let makeReservation return the created Reservation object:
public Reservation makeReservation(int checkIn, int checkOut)//Other parameters
{
reservation = new Reservation(checkIn, checkOut);
return reservation;
}
(You could also create a getter for reservation)
Then change your addReservation like this:
public void addReservation(Reservation res)
{
reservations.add(res);
}
And then just add it like this:
HotelReservationSystem hrs = new HotelReservationSystem();
Reservation res = hrs.makeReservation();
Room room = new Room();
room.addReservation(res);
However, you might want to rethink your model. Right now your HotelReservationSystem is creating a reservation and only saves that one, overwriting old ones. What happens if you create more than one? Also how can you get the reservations for a certain room given the HotelReservationSystem object? Just some things to think about...
I believe you must have tried this
public void addReservation(Reservation reservation)
{
reservations.add(reservation);
}
but the problem here is that your list reservations is null and will throw null pointer exception. So better initialize it at declaration. So change this
private ArrayList<Reservation> reservations;
to
private ArrayList<Reservation> reservations = new ArrayList<Reservation>();
And in your makeReservation method of Hotel class do this:
Room room = new Room();
room.addReservation(reservation);
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.
So, I have already created an ArrayList<>, say Staff List.
private List<Staff> staffs = new ArrayList<Staff>();
public StaffFacade() {
staffs.add(new Staff("1", "James"));
staffs.add(new Staff("2", "Mike"));
staffs.add(new Staff("3", "Lina"));
staffs.add(new Staff("4", "John"));
}
public List<Staff> getStaffs() {
return staffs;
}
And I want to create another List that contains Staff List (by adding), so that I don't have to add the same Staff in StaffFacade?
I already created this BorrowFacade:
private List<Borrow> borrows = new ArrayList<Borrow>();
public BorrowFacade() {
borrows.add(new Borrow()) //How do I add this?
}
public List<Borrow> getBorrows() {
return borrows;
}
Referring to my question above, I don't know how to add new Staff List that has already been created.
This is the constructor for the Borrow List:
public Borrow(Date dueDate, Staff staff, Book books) {
this.dueDate = dueDate;
this.staff = staff;
this.books = books;
}
Of course, I put Date there because I wanted to add Date inside the List too.
MAJOR EDIT
Okay so let me try to put it this way. I have 4 classes which is StaffFacade, BorrowFacade, Borrow and Staff.
This is what I wrote inside StaffFacade:
public class StaffFacade {
private List<Staff> staffs = new ArrayList<Staff>();
public StaffFacade() {
staffs.add(new Staff("1", "James"));
staffs.add(new Staff("2", "Mike"));
staffs.add(new Staff("3", "Lina"));
staffs.add(new Staff("4", "John"));
}
public List<Staff> getStaffs() {
return staffs;
}
}
BorrowFacade:
public class BorrowFacade {
private List<Borrow> borrows = new ArrayList<Borrow>();
public BorrowFacade() {
borrows.add(staffsList);
}
public List<Borrow> getBorrows() {
return borrows;
}
}
Borrow (parts of it, the rest are just setters and getters)
public class Borrow {
String id;
Date dueDate;
Staff staff;
Book books;
public Borrow(String id, Date dueDate, Staff staff, Book books) {
this.id = id;
this.dueDate = dueDate;
this.staff = staff;
this.books = books;
}
Staff:
public class Staff{
String id, name;
public Staff(String id, String name) {
this.id = id;
this.name = name;
}
The problem is in BorrowFacade. I don't know how to add List that has been created in StaffFacade into BorrowFacade's List which is List<Borrow> borrows;
I'm very sorry for the confusion. If anything please ask me. I really want this program to work.
If you have a collection you can addAll(someOtherCollection); but I am not sure I fully understand your question: you refer to a 'constructor for the Borrow List' but you show a constructor for a Borrow class which is not a list.
You seem to be mixing up an instance of an individual class (e.g. Book) with a collection or plurality of that class: Book books (why is it plural? What are you trying to express?)
Edit:
Based on you comment, I think you're trying to understand how to construct the Borrow objects to be placed in the list.
The difference between constructed the Staff List is that you 'know' the staff ahead of time - albeit these are canned values.
The Borrow object seems to express a particular person borrowing a particular book due back on a certain date. If so, you need to have these details somewhere, for example from a database. The reason you're having trouble is you're trying to construct these objects in your Facade instead of just encapsulating ones that already exist.
public class Facade {
private List<Borrow> borrows = new ArrayList<Borrow>();
// Pass the items in to the constructor
public Facade(List<Borrow> borrows) {
this.borrows.addAll(borrows);
}
// You could call this externally in a loop to populate one by one
public void addBorrow(Borrow borrow) {
borrows.add(borrow);
}
}
To restate: your Staff and your Borrow objects have to come from somewhere, so if they're already in a collection, use addAll, if not, just iterate the list and call add. Don't construct the objects in your Facades.
Edit 2:
In response to your amended question, you can't do this. You're trying to add a list of a particulr object (Staff) in to a list of another type of object (Borrow). This is just inherently wrong. I don't quite know how else to say it. If you asked me to give you a List of my favourite Stack Overflow questions, would you expect to find my favourite Stack Overflow user in that list? This is the fundamental nature of type safety. Now, if you asked me to give you a list of my Favourite Things then it is perfectly reasonable to expect to find various types of things in there - Stack Overflow Questions, Wines, Foods, etc. because they would conceptually share a common Favourite parent class or interface.
To be frank, I think you neeed to (re-)read up on the basic nature of Java generics and type safety, but in pursuit of the almighty reputation, here goes:
Note: I'm using StaffMember and BorrowedItem as names here to try to illustrate the value of good naming conventions.
You seem to want a Facade class for reasons none of us understand. Okay, we can accept that. Your Facade class seems to contain a list of objects. You have created multiple classes to accomplish this, with no discernable difference between the two except which objects are listed inside. Generics to the rescue:
public class Facade<T> {
private List<T> list = new ArrayList<T>();
public Facade(List<T> existingList) {
list.addAll(existingList);
}
}
This facade holds a list of objects, meaning you can do this:
List<StaffMember> staffMembers= new ArrayList<StaffMember>();
// .. assume list is populated here
Facade<StaffMember> staffMembersFacade = new Facade<StaffMember>(staffMembers);
Likewise, with the same facade class:
List<BorrowedItem> borrowedItems = new ArrayList<BorrowedItem>();
// ... populate borrowed items
Facade<BorrowedItem> borrowedItemsFacade = new Facade<BorrowedItem<(borrowedItems);
But you aren't adding StaffMember objects to the borrowedItemsFacade. At least not directly - in your example a BorrowedItem has a Date and it also points to which StaffMember borrowed it.
So at this point you have two lists - a list of StaffMembers, and a list of BorrowedItems but you really have to ask yourself what purpose does this serve? Doesn't it make more sense for a single StaffMember to have a List<BorrowedItem> to keep track of all the items they borrowed?
class BorrowedItem {
Date dueDate;
StaffMember borrower;
}
class StaffMember {
String name;
List<BorrowedItem> borrowedItems;
}
Now this provides the opportunity to add a function to the StaffMember like this:
List<BorrowedItem> getOverdueItems() {
List<BorrowedItem> overdueItems = new ArrayList<BorrowedItem>();
Date today = getTodaysDate(); // Calendar.getInstance etc.
for (BorrowedItem borrowedItem : borrowedItems) {
Date dueDate = borrowedItem.getDueDate();
if (today.after(dueDate)) {
overdueItems.add(borrowedItem);
}
}
return overdueItems;
}
Do you see how you need to create meaningful relationships between these classes in order for there to be anything useful to happen?
Then you can add functions to let someone lend an item to another person, or take something from someone, etc.
So yeah, Collections.addAll is what you're looking for, I think.
Does anyone know a library or some at least some research on creating and using persistent data structures in Java? I don't refer to persistence as long term storage but persistence in terms of immutability (see Wikipedia entry).
I'm currently exploring different ways to model an api for persistent structures. Using builders seems to be a interesting solution:
// create persistent instance
Person p = Builder.create(Person.class)
.withName("Joe")
.withAddress(Builder.create(Address.class)
.withCity("paris")
.build())
.build();
// change persistent instance, i.e. create a new one
Person p2 = Builder.update(p).withName("Jack");
Person p3 = Builder.update(p)
.withAddress(Builder.update(p.address())
.withCity("Berlin")
.build)
.build();
But this still feels somewhat boilerplated. Any ideas?
Builders will make your code too verbose to be usable. In practice, almost all immutable data structures I've seen pass in state through the constructor. For what its worth, here are a nice series of posts describing immutable data structures in C# (which should convert readily into Java):
Part 1: Kinds of Immutability
Part 2: Simple Immutable Stack
Part 3: Covariant Immutable Stack
Part 4: Immutable Queue
Part 5: Lolz! (included for completeness)
Part 6: Simple Binary Tree
Part 7: More on Binary Trees
Part 8: Even More on Binary Trees
Part 9: AVL Tree Implementation
Part 10: Double-ended Queue
Part 11: Working Double-ended Queue Implementation
C# and Java are extremely verbose, so the code in these articles is quite scary. I recommend learning OCaml, F#, or Scala and familiarizing yourself with immutability with those languages. Once you master the technique, you'll be able to apply the same coding style to Java much more easily.
I guess the obvious choices are:
o Switch to a transient data structure (builder) for the update. This is quite normal. StringBuilder for String manipulation for example. As your example.
Person p3 =
Builder.update(p)
.withAddress(
Builder.update(p.address())
.withCity("Berlin")
.build()
)
.build();
o Always use persistent structures. Although there appears to be lots of copying, you should actually be sharing almost all state, so it is nowhere near as bad as it looks.
final Person p3 = p
.withAddress(
p.address().withCity("Berlin")
);
o Explode the data structure into lots of variables and recombine with one huge and confusing constructor.
final Person p3 = Person.of(
p.name(),
Address.of(
p.house(), p.street(), "Berlin", p.country()
),
p.x(),
p.y(),
p.z()
);
o Use call back interfaces to provide the new data. Even more boilerplate.
final Person p3 = Person.of(new PersonInfo(
public String name () { return p.name(); )
public Address address() { return Address.of(new AddressInfo() {
private final Address a = p.address();
public String house () { return a.house() ; }
public String street () { return a.street() ; }
public String city () { return "Berlin" ; }
public String country() { return a.country(); }
})),
public Xxx x() { return p.x(); }
public Yyy y() { return p.y(); }
public Zzz z() { return p.z(); }
});
o Use nasty hacks to make fields transiently available to code.
final Person p3 = new PersonExploder(p) {{
a = new AddressExploder(a) {{
city = "Berlin";
}}.get();
}}.get();
(Funnily enough I was just put down a copy of Purely Functional Data Structures by Chris Okasaki.)
Have a look at Functional Java. Currently provided persistent datastructures include:
Singly-linked list (fj.data.List)
Lazy singly-linked list (fj.data.Stream)
Nonempty list (fj.data.NonEmptyList)
Optional value (a container of length 0 or 1) (fj.data.Option)
Set (fj.data.Set)
Multi-way tree (a.k.a. rose tree) (fj.data.Tree)
Immutable map (fj.data.TreeMap)
Products (tuples) of arity 1-8 (fj.P1..P8)
Vectors of arity 2-8 (fj.data.vector.V2..V8)
Pointed list (fj.data.Zipper)
Pointed tree (fj.data.TreeZipper)
Type-safe, generic heterogeneous list (fj.data.hlist.HList)
Immutable arrays (fj.data.Array)
Disjoint union datatype (fj.data.Either)
A number of usage examples are provided with the binary distribution. The source is available under a BSD license from Google Code.
I implemented a few persistent data structures in Java. All open source (GPL) on Google code for anyone who is interested:
http://code.google.com/p/mikeralib/source/browse/#svn/trunk/Mikera/src/mikera/persistent
The main ones I have so far are:
Persistent mutable test object
Persistent hash maps
Persistent vectors/lists
Persistent sets (including a specialised persistent set of ints)
Follow a very simple tentative with dynamic proxy:
class ImmutableBuilder {
static <T> T of(Immutable immutable) {
Class<?> targetClass = immutable.getTargetClass();
return (T) Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class<?>[]{targetClass},
immutable);
}
public static <T> T of(Class<T> aClass) {
return of(new Immutable(aClass, new HashMap<String, Object>()));
}
}
class Immutable implements InvocationHandler {
private final Class<?> targetClass;
private final Map<String, Object> fields;
public Immutable(Class<?> aTargetClass, Map<String, Object> immutableFields) {
targetClass = aTargetClass;
fields = immutableFields;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("toString")) {
// XXX: toString() result can be cached
return fields.toString();
}
if (method.getName().equals("hashCode")) {
// XXX: hashCode() result can be cached
return fields.hashCode();
}
// XXX: naming policy here
String fieldName = method.getName();
if (method.getReturnType().equals(targetClass)) {
Map<String, Object> newFields = new HashMap<String, Object>(fields);
newFields.put(fieldName, args[0]);
return ImmutableBuilder.of(new Immutable(targetClass, newFields));
} else {
return fields.get(fieldName);
}
}
public Class<?> getTargetClass() {
return targetClass;
}
}
usage:
interface Person {
String name();
Person name(String name);
int age();
Person age(int age);
}
public class Main {
public static void main(String[] args) {
Person mark = ImmutableBuilder.of(Person.class).name("mark").age(32);
Person john = mark.name("john").age(24);
System.out.println(mark);
System.out.println(john);
}
}
grow directions:
naming policy (getName, withName, name)
caching toString(), hashCode()
equals() implementations should be straightforward (although not implemented)
hope it helps :)
It is very difficult, if not impossible, to make things immutable that ain't designed so.
If you can design from ground up:
use only final fields
do not reference non immutable objects
Do you want immutability :
so external code cannot change the data?
so once set a value cannot be changed?
In both cases there are easier ways to accomplish the desired result.
Stopping external code from changing the data is easy with interfaces:
public interface Person {
String getName();
Address getAddress();
}
public interface PersonImplementor extends Person {
void setName(String name);
void setAddress(Address address);
}
public interface Address {
String getCity();
}
public interface AddressImplementor {
void setCity(String city);
}
Then to stop changes to a value once set is also "easy" using java.util.concurrent.atomic.AtomicReference (although hibernate or some other persistence layer usage may need to be modified):
class PersonImpl implements PersonImplementor {
private AtomicReference<String> name;
private AtomicReference<Address> address;
public void setName(String name) {
if ( !this.name.compareAndSet(name, name)
&& !this.name.compareAndSet(null, name)) {
throw new IllegalStateException("name already set to "+this.name.get()+" cannot set to "+name);
}
}
// .. similar code follows....
}
But why do you need anything more than just interfaces to accomplish the task?
Google Guava now hosts a variety of immutable/persistent data structures.