RxJava operators - java

I'm learn rxjava using this article: http://blog.danlew.net/2014/09/22/grokking-rxjava-part-2/
and can't reproduce first example of this article
I did next:
Observable<List<String>> query(String text); //Gradle: error: missing method body, or declare abstract
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
query.subscribe(urls -> { //Gradle: error: cannot find symbol variable query
for (String url : urls) {
System.out.println(url);
}
});
}
But I have an errors, which I added as comments
What I did wrong?

Java 8 lambdas aside, most of the people here are missing the fact that your code won't compile regardless RetroLambda or any other nifty tool that you find somewhere to work around the missed lambda feature in Android...
So, take a close look to your code, you even had added some comments to the snippet which are actually explaining you why you are having some compilation errors:
1 You have a method with an empty body:
Observable<List<String>> query(String text);
So, add a method body to it and problem solved. What do you want to do? You don't know yet? Then add a dummy or empty body and work that out later:
Observable<List<String>> query(String text) {
return Observable.just(Arrays.asList("url1", "url2"));
}
2 There is no query variable at all in your code. What you've got is a query method, and the syntax to use methods requires you to use braces:
query("whatever").subscribe(urls -> {
for (String url : urls) {
System.out.println(url);
}
});
Now add the RetroLambda or use anonymous classes and you are done. Bear in mind that nothing out of this will add much functionality to your code but will solve just those compilation errors. Now ask yourself what do you want to do in your query method and carry on.
Note: An Observable object is a stream of data, which basically means that you might get zero elements, one element, or many; all of them instances of the specified type. So your code seems to expect a stream of lists of strings, if what you really want is a stream of strings, then replace Observable<List<String>> for Observable<String>.

By Gradle: error: you mean compilation error? You should probably put parentheses between query and .subscribe(urls -> { as this is not a variable or class filed but method instead, so you should call it to get Observable to subscribe to.
Well, also you need to implement query method to return Observable, for example like this:
private Observable<String> query() {
return Observable.just("one", "two", "three");
}
You'll get another build error because of Java 8 but as already mentioned in comments you can easily use retrolamda with gradle to fix the problem. Otherwise you can use Android Studio quick fixes to convert java 8 lambdas into java 6 anonymous classes.

Related

How to pass Mono<> result from previous step to the next doOnSuccess() method

Let's say that I have a method addVoteToSong like:
public Mono<Map<Song, VoteKind>> addVoteToSong(Principal principal, String songId, VoteKind voteKind) {
return
userRepository.findUserByUsername(principal.getName())
.doOnSuccess(song -> songRepository.findSongById(songId))
.doOnSuccess(vote -> voteRepository.add(Vote.builder().song()))
.//(the rest of the code)
}
I want to pass a result from the line:
userRepository.findUserByUsername(principal.getName())
and
.doOnSuccess(song -> songRepository.findSongById(songId))
to the built object in the line:
.doOnSuccess(vote -> voteRepository.add(Vote.builder().song(here result from findSongById).user(here result from findUserByUsername))
Here comes the question, is it possible to reuse previous API call result in the next doOnSuccess method or I should split find API calls at the same time, giving up on Reactor's cascading operations? On the internet, I have found examples with single save method without basing on the indirect result of the reactive stream and that's why question occurred. I will be grateful for suggestions on how to reach a goal.
Martin,
First of all, be aware that .doOnXXX are just callbacks that will be executed on some archived conditions. You should avoid putting a business logic inside of them.
Coming back to the question, the first idea that comes to my mind is to benefit from zip operator. So you have to put 2 publishers .findUserByUsername and .findSongById and combine the result using BiFunction. So you can try the following:
public Mono<Map<Song, VoteKind>> addVoteToSong(Principal principal, String songId, VoteKind voteKind) {
return Mono
.zip(
userRepository.findUserByUsername(principal.getName()),
songRepository.findSongById(songId),
(user, song) -> voteRepository.add(Vote.builder().song(song).user(user).build())
)
.flatMap(Function.identity())
// your code is here
}

JMeter, postprocessing a sample

in my project i would want to implement a plugin for JMeter.
So currently I am stuck at sampler - postprocessing step.
#Override
public void postProcessSampler(HTTPSamplerBase sampler, SampleResult result)
{
super.postProcessSampler(sampler, result);
String postData = sampler.getPropertyAsString(HTTPSamplerBase.ARGUMENTS);
// ...
// apply some operations to postData
// ...
//
// try to write it back to sampler : approach1
// sampler.removeProperty(HTTPSamplerBase.ARGUMENTS);
// sampler.addNonEncodedArgument(HTTPSamplerBase.ARGUMENTS, postData, "");
// Fails
}
So at the postprocessing step i would like to change the request body, whcih is usually stored in HTTPSamplerBase.ARGUMENTS property. However, somehow i cannot set anything to this field. Redefining it with another string gives me a class cast error. If I try operating with strings, then i get invocation exception...
So my question is, what is the correct way to change the sampler's post body?
Regards and thank you
Try out HTTPSamplerBase.getArguments() function instead, example code:
sampler.getArguments().removeAllArguments();
sampler.addNonEncodedArgument("foo","bar","");
sampler.setPostBodyRaw(true);
Also be aware that for this form of post-processing you don't even need to come up with a plugin, all can be done via JSR223 PostProcessor and Groovy language. The above code should work just fine

Android NullPointerException - Debugging a specific line

If I have a line like this:
var.getSomething().getSomethingElse().setNewValue(stuff.getValue().getWhatever());
If that line creates a NullPointerException, is there any way of finding out which method is returning a null value?
I believe I was able to split the line at every dot and get the exception showing which line was failing. But I can't get that to work anymore (maybe I remember incorrectly).
Is the only good debugging possibility to write it like this?
a = var.getSomething();
b = a.getSomehingElse();
c = stuff.getValue();
d = c.getWhatever();
b.setNewValue(d);
With this I should be able to easily see where the exception happens. But it feels inefficient and ugly to write this way.
I use Android Studio. Used Eclipse before but moved to Android Studio some time ago.
You might want to put every part into "Watches":
But I'm pretty sure that both Eclipse and Android Studio would let you inspect the content by just a selection of the part you' re interested in (if you are in debug mode)
The best I can advice for you is to use #Nullable and #NonNull annotations for all methods with return values. It would not help you to get line where null pointer is but would help to prevent such situations in future.
So if method may return null and you have it in call sequence you will get warning from Android Studio about this. In this case it is better to break sequence and check for null.
For example:
private static class Seq {
private final Random rand = new Random();
#NonNull
public Seq nonNull() {
return new Seq();
}
#Nullable
public Seq nullable() {
return rand.nextInt() % 100 > 50 ? new Seq() : null;
}
}
If you write new Seq().nonNull().nonNull().nullable().nonNull(); you will get warning from IDE:
Method invocation `new Seq().nonNull().nonNull().nullable().nonNull()` may produce 'java.lang.NullPointerException'
The best solution in this case is to change code like so:
Seq seq = new Seq().nonNull().nonNull().nullable();
if (seq != null) {
seq.nonNull();
}
Don't forget to add it into Gradle build script
compile 'com.android.support:support-annotations:22.+'
I am not positive on the way you are doing it. This makes your code tightly coupled and not unit testable.
var.getSomething().getSomethingElse().setNewValue(stuff.getValue().getWhatever());
Instead do something like
var.getSomething();
that get something internally does whatever you are doing as a part of
getSomethingElse().setNewValue(stuff.getValue().getWhatever())
In the same way getSomethingElse() should perform whatever you are doing as a part of
setNewValue(stuff.getValue().getWhatever())

JEditorPane - setText from ArrayList<String> contents?

I have read through the JEditorPane Docs, from what I can understand you simply need to editorpane.setText(String value); however I am quite new to java and this solution does not work with my code. I think I am missing something obvious but completely out of ideas.
I have created a new tab with this class that extends JEditorPane, this class is designed to open the contents of the file, put them on an array, reverse the array (so latest entry is on the top) then display this list in the JEditorPane (using JeditorPane because I need to make the save url's into hyperlinks),
public class HistoryPane extends JEditorPane{
ArrayList<String> historyToSort = new ArrayList<String>();
public HistoryPane(){
setEditable(false);
historySort();
}
public void historySort() {
try (BufferedReader reader = new BufferedReader(new FileReader("BrowserHistory.txt")))
{
String currentLine;
String newLine = new String("\n");
while ((currentLine = reader.readLine()) != null) {
historyToSort.add(currentLine + newLine);
}
} catch (IOException e) {
e.printStackTrace();
}
Collections.reverse(historyToSort);
System.out.println(historyToSort);
}
{
}
private void displayHistory(){
String sorted = historyToSort.toString();
***** HistoryPane.setText(String sorted); <<<------ PROBLEM SYNTAX.*****
}
}
I have tried multiple different entries into the setText() parenthesis with no luck. What am I missing? Thank You.
NOTE:
This class won't compile because it is reliant on another class (I can't paste all of it) but this code sits within a tabbed pane created by my main class:
Error Message:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Unresolved compilation problems:
Syntax error on token "setText", Identifier expected after this token
Return type for the method is missing
This method requires a body instead of a semicolon
OK, despite the fact that you haven't read the error message, it seems you're really a newbie, so I'll help.
HistoryPane.setText(String sorted);
The above isn't valid Java. A method invocation takes a list of arguments, without a type.
HistoryPane.setText(sorted);
Now that is a valid method invocation. But it tries to invoke a static method called setText() of the class HistoryPane. What you want is to invoke the instance method setText() on the current object. So the valid syntax is
this.setText(sorted);
or simply
setText(sorted);
That should solve this particular compilation error. Don't try to run your app before every compilation error, listed in the Problems view of Eclipse, is fixed.
Note that the above line won't do what you want it to do, but I'll let you investigate what you should do instead.
My advice: don't try using Swing, which is quite a complex beast, if you don't even know how to call a method yet. Start with very simple Java exercises, not involving any GUI, until you're familiar with the Java syntax, and understand how to read, understand and fix basic compilation problems.

How do I create a List of generic arrays in Java?

I've written a class which accepts a generic type, and I'm trying to create an array list of generic arrays within it. I understand that Java can't create generic arrays, but I also know there are workarounds. Is there a way the below code can work, or am I barking up the wrong tree?
public class IterableContainer<T extends IterableItem> {
private T[] itemArray;
// how can i get this following line to work?
private List<T[]> items = new ArrayList<T[10]>();
public IterableContainer() {
... etc ...
Ignore past here - turns out it was an IDE issue.
Left in for continuity of questions and answers.
EDIT:
This also doesn't work:
private List<T[]> items = new ArrayList<T[]>();
with the error:
Syntax error on token ">", VariableDeclaratorId expected after this token
"... barking up the wrong tree..., use a List<List<T>>. Using raw arrays in Java is almost always a code smell, there is no reason not to use the proper collection classes.
It works just fine, you just can't use the T[10] declaration as the length of an array doesn't affect its type.
i.e.
... = new ArrayList<T[]>();
Not saying it's a great idea, but it should be possible with the same restrictions on generic arrays as always. Creating stuff to put in your list will give you a headache.
private List<T[]> items = new ArrayList<T[]>();
works fine in my machine
When you say "I'm developing for mobile devices" ....are you targeting j2me? There is no support for generics in j2metargetng
This is a valid declaration in java (according to spec) and compiles just fine with javac as others have commented.
public class IterableContainer<T extends IterableItem> {
private T[] itemArray;
private List<T[]> items = new ArrayList<T[]>();// valid
..........
}
I believe the error you are seeing is not emitted from Eclipse, possibly coming from an Android SDK configured in Eclipse. If you create a Java Project in Eclipse, this code should work just fine. If you use this in an Android Project in Eclipse, you are likely to run into this one. I had this error when running this code from an Android project :
# guarantee(_name_index != 0 && _signature_index != 0) failed: bad constant pool index for fieldDescriptor
Sounds like you are restricted in an Android project, unfortunately.
You have not defined T in this code.
If you are creating a generic class, you need to write:
public class <T extends IterableItem> IterableContainer...
The next problem in your code is that you are trying to initilize items of ArrayList during its construction. It is impossible. You should rather write:
private List<T[]> items = new ArrayList<T[]>();

Categories

Resources