I hava a set of methods of type boolean which are settings things up. Each method return true if busines logic was successfully executed and false if anything went wrong. I would like to break chain at first fail.
Are there any good practicies?
ATM I am doing something like this:
if (taskIsDone(task) && taskGenerateReport(task) && taskReportIsDone(task) && taskProcessReport(task)){
log.info("Processing of task {} is done", task.getName());
} else {
log.error("Task {} finished with error", task.getName());
}
Something like this works in my dev env but if scenario when for any reason order of methods would change logic like this is useless.
Could anyone give me a hint how to make it right?
As the other people said, the order of execution is from the left to the right.
In your case, I would call task.isDone() or task.generateReport() and so on, as it's related to the task which is in your case probably a domain object.
Related
I'm in the process of migrating an AsyncTaskLoader to RxJava, trying to understand all the details about the RxJava approach to concurrency. Simple things were running ok, however I'm struggling with the following code:
This is the top level method that gets executed:
mCompositeDisposable.add(mDataRepository
.getStuff()
.subscribeOn(mSchedulerProvider.io())
.subscribeWith(...)
mDataRepository.getStuff() looks like this:
public Observable<StuffResult> getStuff() {
return mDataManager
.listStuff()
.flatMap(stuff -> Observable.just(new StuffResult(stuff)))
.onErrorReturn(throwable -> new StuffResult(null));
And the final layer:
public Observable<Stuff> listStuff() {
Log.d(TAG, ".listStuff() - "+Thread.currentThread().getName());
String sql = <...>;
return mBriteDatabase.createQuery(Stuff.TABLE_NAME, sql).mapToList(mStuffMapper);
}
So with the code above, the log will print out .listStuff() - main, which is not exactly what I'm looking for. And I'm not really sure why. I was under impression that by setting subscribeOn, every event pulled from the chain will be processed on the thread specified in the subscribeOn method.
What I think is happening, is that the source-aka-final-layer code, before reaching mBriteDatabase, is not from the RxJava world and therefore is not an event until createQuery is called. So I probably need some sort of a wrapper? I've tried applying .fromCallable, however that's a wrapper for non Rx code, and my database layer returns an observable...
Your Log.d call happens
immediately when listStuff gets called
which is immediately after getStuff gets called
which is the first thing happening in the top level code fragment you show us.
If you need to do it when the subscription happens, you need to be explicit:
public Observable<Stuff> listStuff() {
String sql = <...>;
return mBriteDatabase.createQuery(Stuff.TABLE_NAME, sql)
.mapToList(mStuffMapper)
.doOnsubscribe(() -> Log.d(TAG, ".listStuff() - "+Thread.currentThread().getName()));
}
For example I have something like this:
public void saveFoodatas(List<Foodata> foodataList) {
DatabaseHelper.database.beginTransaction();
try {
for (Foodata foodata : foodataList) {
saveFoodata(foodata);
}
DatabaseHelper.database.setTransactionSuccessful();
}
finally {
DatabaseHelper.database.endTransaction();
}
}
Where DatabaseHelper is a class extending SQLiteOpenHelper and database is a SQLiteDatabase.
In this function I am trying to make it so you save/commit a lot of objects to the database, but if there is a failure, then don't commit any of the changes.
I believe that what it's currently set up to do correctly (if there is an error, it leaves the try block I think and goes straight to finally since there is no catch), but my question is how to properly trigger the failure condition. Do I need saveFoodata to "throw an exception"? If the function encounters some kind of failure without me doing any try/catch/throwing, does that count too? How exactly do I handle saveFooData()?
I think you are on the right track. You need to abort the transaction if an error occurs. You also need to alert the user of the problem. This means that saveFoodata() and saveFoodatas() should throw an exception so that the UI code can display a message to the user,
I'm working on an IRC bot that should handle some user commands, lets take !login <username> <password> for example. Sometimes the user forgets to enter their password, so instead of sending !login myUser hunter2 they might use !login myUser. In this case, the user should be replied to with an error message. The method that actually handles the command handleCommand is always wrapped by another method wrapperMethod. Which of the following ways should I use to handle user errors: should handleCommand just message the user about what happened and exit itself, or should it throw an exception with the error message and let wrapperMethod do the rest? (String[] command is the original command without the ! and split by spaces, so !login myUser hunter2 would become {"login", "myUser", "hunter2"})
Using exceptions:
public void wrapperMethod(Object sender, Object receiver, String[] command) {
try {
handleCommand(sender, receiver, command);
catch(CommandExecutionException e) {
receiver.sendTo(sender, e.getMessage());
}
}
private void handleCommand(Object sender, Object receiver, String[] command) {
if(command.length != 3)
throw new CommandExecutionException("Things went wrong");
//Do things
}
Not using exceptions:
public void wrapperMethod(Object sender, Object receiver, String[] command) {
handleCommand(sender, receiver, command);
}
private void handleCommand(Object sender, Object receiver, String[] command)
if(command.length != 3) {
receiver.sendTo(sender, "Things went wrong");
return;
}
//Do things
}
Which type should I prefer and why? Right now, I'm thinking of going with exceptions simply because I can save a few lines of code that I really don't need. When a user error is detected, handleCommand is always halted immediately. There's also the possiblility of having handleCommand return Optional<Error> or something like that, but this seems really fishy.
I prefer option with exceptions, because it separates normal processing from error handling.
In second option method handleCommand is responsible for both.
First option follows Single responsibility principle: method handleCommand handles correct flow, if something goes wrong throw exception and allow someone else cares the problem.
Moreover, assume that within section
//Do things
you find other error. If you use exception, you may keep consistent and clean pattern that any error triggers exception and someone who catch the exception cares correct handling.
Don't worry that exceptions are expensive; planes are more expensive that bikes, but if you go for vacation to Bali, use rather plane than bike (not applicable for Bali citizens:) ). Exceptions are designed for exceptions, as long as you don't use them in regular processing, it is OK.
Exceptions are expensive. Using them as flow control is strongly discouraged. It also means that your code could complete abruptly, and makes it harder to debug or read.
I'd go a different route: use Hibernate Validators. They're not difficult to set up or establish in your code, and using them means that your input is validated before you ever attempt to manipulate things. It also keeps your validation logic and actual business logic separate.
If you don't want to go that route, I'd encourage the latter approach - although, I'd use an else instead of return from a void method.
I am fairly new to Java and extremely new to concurrency. However, I have worked with C# for a while. It doesn't really matter, but for the sake of example, I am trying to pull data off a table on server. I want method to wait until data is completely pulled. In C#, we have async-await pattern which can be used like this:
private async Task<List<ToDoItem>> PullItems ()
{
var newRemoteItems = await (from p in remoteTable select p).ToListAsync();
return newRemoteItems;
}
I am trying to have similar effect in Java. Here is the exact code I'm trying to port (Look inside SynchronizeAsync method.)! However, Java Azure SDK works with callbacks. So, I have a few options:
Use wait and notify pattern. Following code doesn't work since I don't understand what I'm doing.
final List<TEntity> newRemoteItems = new ArrayList<TEntity>();
synchronized( this ) {
remoteTable.where().field("lastSynchronized").gt(currentTimeStamp)
.execute(new TableQueryCallback<TEntity>() {
public void onCompleted(List<TEntity> result,
int count,
Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
newRemoteItems.clear();
for (TEntity item: result) {
newRemoteItems.add(item);
}
}
}
});
}
this.wait();
//DO SOME OTHER STUFF
My other option is to move DO SOME OTHER STUFF right inside the callback's if(exception == null) block. However, this would result in my whole method logic chopped off into the pieces, disturbing the continuous flow. I don't really like this approach.
Now, here are questions:
What is recommended way of doing this? I am completing the tutorial on Java concurrency at Oracle. Still, clueless. Almost everywhere I read, it is recommended to use higher level stuff rather than wait and notify.
What is wrong with my wait and notify?
My implementation blocks the main thread and it's considered a bad practice. But what else can I do? I must wait for the server to respond! Also, doesn't C# await block the main thread? How is that not a bad thing?
Either put DO SOME OTHER STUFF into callback, or declare a semaphore, and call semaphore.release in the callback and call semaphore.aquire where you want to wait. Remove synchronized(this) and this.wait.
How to detect that code is running inside eclipse IDE
I am not aware of a generic way to get this kind of information.
One suggestion:
When you start a Java program (or a web server) inside Tomcat, simply add an argument that will indicate that this program is launched by Eclipse.
You can do that by opening the "Open Run Dialog" ("Run" menu), then select your type of application and add in the "Arguments" tab a -DrunInEclipse=true.
In your Java code, you can check the value of the property:
String inEclipseStr = System.getProperty("runInEclipse");
boolean inEclipse = "true".equalsIgnoreCase(inEclipseStr);
This way, if the program is not running inside Eclipse (or unfortunately if you forgot to set the property) the property will be null and then the boolean inEclipse will be equal to false.
Although I agree that having the code detecting a single IDE as the dev env is not an optimal solution, the following code works.
Like others proposed, using a flag at runtime is better.
public static boolean isEclipse() {
boolean isEclipse = System.getProperty("java.class.path").toLowerCase().contains("eclipse");
return isEclipse;
}
1) Create a helper method like:
public boolean isDevelopmentEnvironment() {
boolean isEclipse = true;
if (System.getenv("eclipse42") == null) {
isEclipse = false;
}
return isEclipse;
}
2) Add an environment variable to your launch configuration:
3) Usage example:
if (isDevelopmentEnvironment()) {
// Do bla_yada_bla because the IDE launched this app
}
Actually the code is not being run inside Eclipse, but in a separate Java process started by Eclipse, and there is per default nothing being done by Eclipse to make it any different than any other invocation of your program.
Is the thing you want to know, if your program is being run under a debugger? If so, you cannot say for certain. You CAN, however, inspect the arguments used to invoke your program and see if there is anything in there you do not like.
If your workspace matches some pattern like "/home/user/workspace/Project" you can use the code below:
Boolean desenv = null;
boolean isDevelopment() {
if (desenv != null) return desenv;
try {
desenv = new File(".").getCanonicalPath().contains("workspace");
}
catch (IOException e) {
e.printStackTrace();
}
return desenv;
}
A more generic and precise way, that can be used on any IDE would be loop at:
ManagementFactory.getRuntimeMXBean().getInputArguments()
looking for "-Xdebug" || (starting with) "-agentlib:jdwp=".
I came with this from #saugata comment here.
This is excellent if you want to throw a conditional exception preventing the application from simply exiting. Use a boolean like "ideWait" and add it to Eclipse watch expressions as ideWait=false, so whenever you stop at that throw, and "drop to frame" you can continue debugging happily (I mean it!)
I don't think there is any way to do this. But what I would suggest is just a command line argument such as 'debug'. Then in your main method just do
if (args.length > 0 && args[0].equalsIgnoreCase("debug")) {
// do whatever extra work you require here or set a flag for the rest of the code
}
This way you can also get your extra code to run whenever you want just by specifiying the debug parameter but under normal conditions it will never execute.
This might work if your alternative execution work flow provides a different set of dependencies:
boolean isRunningInEclipe = false;
try {
Workbench.getInstance();
isRunningInEclipe = true;
} catch (NoClassDefFoundError error) {
//not running in Eclipse that would provide the Workbench class
}
You could detect if you're inside a JAR or not, as per Can you tell on runtime if you're running java from within a jar?
Eclipse will run your app from the classes/ dir, whereas most of your end users will be running the app from a JAR.
System.out.println("Is my parent eclipse[.exe]? " +
ProcessHandle.current()
.parent()
.flatMap(parent -> parent.info().command())
.orElse("")
.matches("^.*eclipse(\\.exe)?$"));
You may try something like this:
if (ClassLoader.getSystemResource("org/eclipse/jdt/core/BindingKey.class")!=null){
System.out.println("Running within Eclipse!!!");
} else {
System.out.println("Running outside Eclipse!!!");
}