How to create a AggregationOutput object, to use it later on - java

I feel like I have had to unlearn something about programming lately. I keep going in circles.
I have a try catch in the method I want to use an AggregationOutput object. After the catch, I want to return what I hope are the values of the field I am looking for. That values are what I obtain from an aggregate method, which I can't find any way of storing other than AggregationOutput object.
Something like this:
List<DBObject> results = new ArrayList<DBObject>();
AggregationOutput output = new AggregationOutput(results);
try
{
or
AggregationOutput output = new AggregationOutput(null);
try
{
I am not able to create an AggregationOutput WITHOUT immediatly storing in it the values of the aggregate method. Like this:
AggregationOutput output = collection.aggregate(pipe);
This seems counter intuitive at the very least, if not plaing wrong, which makes me suspect I'm missing a BIG concept which isn't allowing me to use this method (aggregate) properly.
I would like to know what that object need to be declared on it's own, so I can declare, go into the try, instance the object, and then after the catch, return said object.
If there is any other way of doing this, without using AggregationOutput, I would also like to know, because I do not find any way.
edit:
#GET
#Path("/get/{item}/{id}")
#Produces(MediaType.APPLICATION_JSON)
public String get( #PathParam("item") String item, #PathParam("id") String id) {
AggregationOutput output;
try
{
List<DBObject> result = new ArrayList<DBObject>();
output = new AggregationOutput(result);
//here I would operate with the output, then return the result as I usually do, an array or some other object that can be transformed into json

maybe this is worth a try.
instead of doing
public String get()
{
try {}
catch() {}
}
try doing
public String get() throws ExceptionName {}
//assuming you will use get in main
public static void main (String [] args)
{
try { get(); }
catch (ExceptionName e) {}
}
otherwise link me the code and i will try debugging it at my end.

Related

Update a list reference inside a method

In Java we can not reassign a reference inside a method.
So the following does not work:
class SomeClass {
List<PaidOrders> paidOrders;
List<PendingOrders> pendingOrders;
List<CancelledOrders> cancelledOrders;
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist = newOrders;
}
}
But the following does work:
class SomeClass {
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist.clear();
currentOrderlist.addAll(newOrders); // <- extra linear loop
}
}
The problem is that the second example does an extra linear loop to copy from one list to the other.
Question:
I was wondering, is there some design approach so that I could neatly just replace the references instead? I.e. somehow make the first snippet work with some change in the parameters or something?
Update
After the comments I would like to clarify that the currentOrderList can be any of the paidOrders, pendingOrders, cancelledOrders.
The code for process is the same for all types.
Hm. I see two possibilities here. Either you use some wrapper object such as AtomicReference (might be a bit overpowered because of the multi-threading issues) as the argument and then just set it there or you use a consumer.
In the second case your method would look like this:
public void process(List<OrderStatus> data, Consumer<List<Orders>> target) {
List<Person> newOrders = fromOrderStatus(data);
target.accept(newOrders);
}
Then on the calling side you would implement it like this:
process(data, e-> <<targetList>> = e);
If your list will be wrapped by a different object (for example - AtomicReference), then you will be able to change it.
public static void doSomething(AtomicReference<List<Integer>> listAtomicReference){
List<Integer> newIntegers = new ArrayList<>();
listAtomicReference.set(newIntegers);
}
public static void main(String[] args) {
AtomicReference<List<Integer>> listAtomicReference = new AtomicReference<>(Arrays.asList(4));
doSomething(listAtomicReference);
System.out.println(listAtomicReference.get());
}
Output:
[]
Making a public member variable in a class.
With that being said, I wouldn't recommend walking this path.
Is premature optimization really the root of all evil?

Wrong number of arguments on method.invoke

I currently have this code:
public class Pants {
public static void main(String[] args) {
Pants pants = new Pants();
pants.eat(10, 10.3, "Nice.");
Object[] params = {(long)10, 10.3, "Nice."};
Method eatMethod = pants.getClass().getMethods()[0];
try
{
eatMethod.invoke(pants, params);
} catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
}
}
public void eat(long amount, double size, String name) {
System.out.println("You ate");
}
}
It always throws
IllegalArgumentException: wrong number of arguments.
This happened with other methods too. I used the same parameters in eat() as in method.invoke, and the types are the same. The error is thrown on
eatMethod.invoke(pants, params);
As the comments say. We don't know wich method is pants.getClass().getMethods()[0]. Try to get the name with eatMethod.getName() and see if is really the method eat. If
not you can try with this.
java.lang.reflect.Method method;
method = pants.getClass().getMethod("eat", Long.class, Double.class, String.class);
.
.
.
method.invoke(pants,params );
Also... Checking the Java Docs The methods are never sorted
The elements in the returned array are not sorted and are not in any
particular order.
So sometimes your code might work and sometimes not.
It turns out that when I used getMethods()[0], I was getting the main method and calling that, which obviously has no parameters so it didn't work. Ideally I should've used
getMethod("eat", long.class, double.class, String.class)
which does work.

Updating pre-existing documents in mongoDB java driver when you've changed document structure

I've got a database of playerdata that has some pre-existing fields from previous versions of the program. Example out-dated document:
{
"playername": "foo"
}
but a player document generated under the new version would look like this:
{
"playername": "bar",
"playercurrency": 20
}
the issue is that if I try to query playercurrency on foo I get a NullPointerException because playercurrency doesn't exist for foo. I want to add the playercurrency field to foo without disturbing any other data that could be stored in foo. I've tried some code using $exists Example:
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playername", "")));
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playercurrency", 20)));
My thought is that it updates only playercurrency because it doesn't exist and it would leave playername alone becuase it exists. I might be using exists horribly wrong, and if so please do let me know because this is one of my first MongoDB projects and I would like to learn as much as I possibly can.
Do you have to do this with java? Whenever I add a new field that I want to be required I just use the command line to migrate all existing documents. This will loop through all players that don't have a playercurrency and set it to 0 (change to whatever default you want):
db.players.find({playercurrency:null}).forEach(function(player) {
player.playercurrency = 0; // or whatever default value
db.players.save(player);
});
This will result in you having the following documents:
{
"playername" : "foo",
"playercurrency" : 0
}
{
"playername" : "bar",
"playercurrency" : 20
}
So I know that it is normally frowned upon on answering your own question, but nobody really posted what I ended up doing I would like to take this time to thank #Mark Watson for answering and ultimately guiding me to finding my answer.
Since checking if a certain field is null doesn't work in the MongoDB Java Driver I needed to find a different way to know when something is primed for an update. So after a little bit of research I stumbled upon this question which helped me come up with this code:
private static void updateValue(final String name, final Object defaultValue, final UUID key) {
if (!exists(name, key)) {
FindIterable iterable = players.find(new Document("_id", key));
iterable.forEach(new Block<Document>() {
#Override
public void apply(Document document) {
players.updateOne(new Document("_id", key), new Document("$set", new Document(name, defaultValue)));
}
});
}
}
private static boolean exists(String name, UUID key) {
Document query = new Document(name, new Document("$exists", true)).append("_id", key);
return players.count(query) == 1;
}
Obviously this is a little specialized to what I wanted to do, but with little revisions it can be easliy changed to work with anything you might need. Make sure to replace players with your Collection object.

Java pattern for parameters of which only one needs to be non-null?

In the last time I often write long functions that have several parameters but use only one of them and the functionality is only different at a few keypoints that are scattered around the function. Thus splitting the function would create too many small functions without a purpose. Is this good style or is there a good general refactoring pattern for this? To be more clear, an example:
public performSearch(DataBase dataBase, List<List<String>> segments) {performSearch(dataBase,null,null,segments);}
public performSearch(DataBaseCache dataBaseCache,List<List<String>> segments) {performSearch(null,dataBaseCache,null,segments);}
public performSearch(DataBase dataBase, List<String> keywords {performSearch(dataBase,null,keywords,null);}
public performSearch(DataBaseCache dataBaseCache,List<String> keywords) {performSearch(null,dataBaseCache,keywords,null);}
/** either dataBase or dataBaseCache may be null, dataBaseCache is used if it is non-null, else dataBase is used (slower). */
private void performSearch(DataBase dataBase, DataBaseCache dataBaseCache, List<String> keywords, List<List<String>> segments)
{
SearchObject search = new SearchObject();
search.setFast(true);
...
search.setNumberOfResults(25);
if(dataBaseCache!=null) {search.setSource(dataBaseCache);}
else {search.setSource(dataBase);}
... do some stuff ...
if(segments==null)
{
// create segments from keywords
....
segments = ...
}
}
This style of code works but I don't like all those null parameters and the possibilities of calling methods like this wrong (both parameters null, what happens if both are non-null) but I don't want to write 4 seperate functions either... I know this may be too general but maybe someone has a general solution to this principle of problems :-)
P.S.: I don't like to split up a long function if there is no reason for it other than it being long (i.e. if the subfunctions are only ever called in that order and only by this one function) especially if they are tightly interwoven and would need a big amount of parameters transported around them.
I think it is very bad procedural style. Try to avoid such coding. Since you already have a bulk of such code it may be very hard to re-factor it because each method contains its own logic that is slightly different from other. BTW the fact that it is hard is an evidence that the style is bad.
I think you should use behavioral patterns like
Chain of responsibilities
Command
Strategy
Template method
that can help you to change your procedural code to object oriented.
Could you use something like this
public static <T> T firstNonNull(T...parameters) {
for (T parameter: parameters) {
if (parameter != null) {
return parameter;
}
}
throw new IllegalArgumentException("At least one argument must be non null");
}
It does not check if more than one parameter is not null and they must be of the same type, but you could use it like this:
search.setSource(firstNonNull(dataBaseCache, database));
Expecting nulls is an anti-pattern because it litters your code with NullPointerExceptions waiting to happen. Use the builder pattern to construct the SearchObject. This is the signature you want, I'll let you figure out the implementation:
class SearchBuilder {
SearchObject search = new SearchObject();
List<String> keywords = new ArrayList<String>();
List<List<String>> segments = new ArrayList<List<String>>();
public SearchBuilder(DataBase dataBase) {}
public SearchBuilder(DataBaseCache dataBaseCache) {}
public void addKeyword(String keyword) {}
public void addSegment(String... segment) {}
public void performSearch();
}
I agree with what Alex said. Without knowing the problem I would recommend following structure based on what was in the example:
public interface SearchEngine {
public SearchEngineResult findByKeywords(List<String> keywords);
}
public class JDBCSearchEngine {
private DataSource dataSource;
public JDBCSearchEngine(DataSource dataSource) {
this.dataSource = dataSource;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// Find from JDBC datasource
// It might be useful to use a DAO instead of datasource, if you have database operations other that searching
}
}
public class CachingSearchEngine {
private SearchEngine searchEngine;
public CachingSearchEngine(SearchEngine searchEngine) {
this.searchEngine = searchEngine;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// First check from cache
...
// If not found, then fetch from real search engine
SearchEngineResult result = searchEngine.findByKeywords(keywords);
// Then add to cache
// Return the result
return result;
}
}

JMockit | trying to define different return values based on parameters but getting unexpected results

I've got a class like the following:
class A
{
public method doSomething()
{
//....
DAO dataAccessor = new DAO();
List<Object> result1 = dataAccessor.getData(dataAccessor.getSql1());
List<Object> result2 = dataAccessor.getData(dataAccessor.getSql2());
//.. do some stuff with the results
}
Now, I use jMockit for testing the above function, by mocking the DAO class.
This is how my test class looks like:
class A_Test
{
private A myAClass;
#Mocked DAO mockedDAO;
List<Object> resultToSql1, resultToSql2;
// ... Some initializations...
#Test
public void testDoSomething()
{
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getData(withEqual("SQL1")); result = resultToSql1;
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
};
myAClass.doSomething();
}
}
Now, it seems that the second expectation regarding getData() masks the first one, i.e. the mock object behaves as if I never declared the first lines in the expectation (the ones that handle sql1):
The first call to getData() returns empty collection, instead of the values with which I initialized resultToSql1. The second call returns resultToSql2, as expected.
If I comment the following line:
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
the first call is returning what I defined - resultToSql1, and the second returns empty collection.
This makes sense.
So, what am I doing wrong? ?How can I define two different return values from getData() based on the parameters of the call?
Any help would be appreciated.
Thanks!
So, After digging more deeply inside the manual, I found that:
...But what if a test needs to decide the result of a recorded invocation based on the arguments it will receive at replay time? We can do it through a mockit.Delegate instance ...
So, in order to solve the above problem, the expectations block should look like this:
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(anyString);
result = new mockit.Delegate()
{
List<Object> getData(String sql)
{
if (sql.equals("SQL1"))
return resultToSql1;
if (sql.equals("SQL2"))
return resultToSql2;
return null;
}
}
};

Categories

Resources