couchbase connect closed when upsert - java

I have two methods upsert into couchbase. Then I write two Junit tester with springboottest. After one Junit tester completed another test will throw this exception. How to resolve?
There are two upsert methods:I don't know which one methods is better?
public List<RawJsonDocument> upsert2(String generatorId, String idPrefix, List<String> contents)
{
List<RawJsonDocument> rjd = new ArrayList<RawJsonDocument>(contents.size());
Observable.from(contents).flatMap(new Func1<String,Observable<String>>(){
#Override
public Observable<String> call(String t)
{
return bucket.async().counter(generatorId, 1)
.map(jsonLongDocument -> {
String idStr = idPrefix + generatorId + jsonLongDocument.content();
String jsonStr = idStr + "=" + t;
return jsonStr;
});
}}).subscribe(new Action1<String>() {
#Override
public void call(String t)
{
String[] s = t.split("[=]");
LOGGER.debug("\n methord2 generatorId:" + s[0] + "\n content:" + s[1]);
bucket.async().upsert(RawJsonDocument.create(s[0],s[1]));
}});
return rjd;
}
public List<RawJsonDocument> upsert1(String generatorId, String idPrefix, List<String> contents)
{
if(contents == null)
{
return null;
}
List<RawJsonDocument> rjd = new ArrayList<RawJsonDocument>(contents.size());
Observable.from(contents).flatMap(new Func1<String,Observable<RawJsonDocument>>(){
#Override
public Observable<RawJsonDocument> call(String t)
{
return bucket.async().counter(generatorId, 1)
.map(jsonLongDocument -> {
String idStr = idPrefix + generatorId + jsonLongDocument.content();
LOGGER.debug("\n method3 generatorId:" + idStr + "\n content:" + t);
return RawJsonDocument.create(idStr,t);
});
}}).subscribe(new Action1<RawJsonDocument>() {
#Override
public void call(RawJsonDocument t)
{
rjd.add(bucket.async().upsert(t).toBlocking().single());
}});
return rjd;
}
This is my Junit Tester:
#Test
public void testIncrementIds3()
{
assertThat(generatorId.upsert2("counter", "idprefix", Arrays.asList("aabbccdd","ffddeeaa")).size(),is(2));
assertThat(generatorId.upsert1("counter", "idprefix", Arrays.asList("aabbccdd","ffddeeaa")).size(),is(2));
}

Related

CompletableFutures: processing of CompletableFuture chains in parallel

I am designing an asynchronous call with CompletableFutures. This is a batch call, where I need to process several entities at once. At the end of the call I have to collect information about the status of the processing of every item.
As the input I have an array of ids of those entities. This is a complex entity, I have to place several DAO calls in order to compile an entity into an object. Each of DAO methods return CompletableFuture<PartX>.
I am chaining those DAO calls because if one of the pieces does not exist I won't be able to construct a whole object. Here is how my snippet looks like:
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
public class CfChainsAllOfTest {
private DAO dao = new DAO();
public static void main(String[] args) {
CompletableFuture<Void> resultPrintingCf = new CfChainsAllOfTest().fetchAllInParallelAndCollect(Lists.newArrayList(1l, 2l, 3l)).thenAccept(results -> {
System.out.println("[" + Thread.currentThread().getName() + "]" + results);
});
resultPrintingCf.join();
}
private CompletableFuture<List<Item>> fetchAllInParallelAndCollect(List<Long> ids) {
List<CompletableFuture<Item>> cfs = Lists.newArrayList();
for (Long id : ids) {
// I want this to be an instant non-blocking operation
cfs.add(fetchSingle(id));
System.out.println("[" + Thread.currentThread().getName() + "]" + "After completable future was added to the list, id=" + id);
}
return waitAllOfAndCollect(cfs);
}
private CompletableFuture<Item> fetchSingle(Long id) {
return getPartCAndSetOnItem(new Item(id)).thenCompose(this::getPartBAndSetOnItem).thenCompose(this::getPartAAndSetOnItem);
}
public CompletableFuture<Item> getPartCAndSetOnItem(Item item) {
return dao.getPartC(item.getId()).thenCompose(partC -> {
CompletableFuture<Item> cf = new CompletableFuture<>();
item.setPartC(partC);
cf.complete(item);
return cf;
});
}
public CompletableFuture<Item> getPartBAndSetOnItem(Item item) {
return dao.getPartB(item.getId()).thenCompose(partB -> {
CompletableFuture<Item> cf = new CompletableFuture<>();
item.setPartB(partB);
cf.complete(item);
return cf;
});
}
public CompletableFuture<Item> getPartAAndSetOnItem(Item item) {
return dao.getPartA(item.getId()).thenCompose(partA -> {
CompletableFuture<Item> cf = new CompletableFuture<>();
item.setPartA(partA);
cf.complete(item);
return cf;
});
}
private static <T> CompletableFuture<List<T>> waitAllOfAndCollect(List<CompletableFuture<T>> futures) {
CompletableFuture<Void> allDoneFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
return allDoneFuture.thenApply(v -> futures.stream().map(future -> future.join()).collect(Collectors.<T> toList()));
}
static class DAO {
public CompletableFuture<PartC> getPartC(Long id) {
return CompletableFuture.supplyAsync(() -> {
System.out.println("[" + Thread.currentThread().getName() + "]" + "Fetching Part C from database for id=" + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("[" + Thread.currentThread().getName() + "]" + "Part C fetched from db for id=" + id);
return new PartC();
});
}
public CompletableFuture<PartB> getPartB(Long id) {
return CompletableFuture.supplyAsync(() -> {
System.out.println("[" + Thread.currentThread().getName() + "]" + "Fetching Part B from database for id=" + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("[" + Thread.currentThread().getName() + "]" + "Part B fetched from db for id=" + id);
return new PartB();
});
}
public CompletableFuture<PartA> getPartA(Long id) {
return CompletableFuture.supplyAsync(() -> {
System.out.println("[" + Thread.currentThread().getName() + "]" + "Fetching Part A from database for id=" + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("[" + Thread.currentThread().getName() + "]" + "Part A fetched from db for id=" + id);
return new PartA();
});
}
}
static class Item {
private final Long id;
private PartA partA;
private PartB partB;
private PartC partC;
public Item(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public PartA getPartA() {
return partA;
}
public void setPartA(PartA partA) {
this.partA = partA;
}
public PartB getPartB() {
return partB;
}
public void setPartB(PartB partB) {
this.partB = partB;
}
public PartC getPartC() {
return partC;
}
public void setPartC(PartC partC) {
this.partC = partC;
}
#Override
public String toString() {
return "Item [id=" + id + ", partA=" + partA + ", partB=" + partB + ", partC=" + partC + "]";
}
}
static class PartA {
#Override
public String toString() {
return "Part A";
}
}
static class PartB {
#Override
public String toString() {
return "Part B";
}
}
static class PartC {
#Override
public String toString() {
return "Part C";
}
}
}
The problem is that processing for each item is not really done in parallel because of the chaining. It looks like chaining of CompletableFutures is a blocking call. I would expect the chain of CFs to return variable of CompletableFuture<Whole> immediately and only after that start computing the value.
That said, what would be the best way to achieve such behavior? Thanks.
The problem is with this method:
private CompletableFuture<Item> fetchSingle(Long id) {
return getPartCAndSetOnItem(new Item(id)).thenCompose(this::getPartBAndSetOnItem).thenCompose(this::getPartAAndSetOnItem);
}
Basically you are telling: get part C, then get part B, then get part A.
Instead, you should call the 3 methods, then merge the results – though that might not be necessary here due to the way you just store the result on the Item (pay attention to the Java memory model here, as your Item is not synchronized here: it might not work properly for more complex examples).
So, basically:
private CompletableFuture<Item> fetchSingle(Long id) {
Item result = new Item(id);
CompletableFuture<?> c = getPartCAndSetOnItem(result);
CompletableFuture<?> b = getPartBAndSetOnItem(result);
CompletableFuture<?> a = getPartAAndSetOnItem(result);
return CompletableFuture.allOf(a, b, c).thenApply(__ -> result);
}
Of course, the drawback is that you perform all 3 calls even if one fails, but you cannot have your cake and eat it…
As a side note, your getPartXAndSetOnItem() methods can be simplified to
public CompletableFuture<Item> getPartXAndSetOnItem(Item item) {
return dao.getPartX(item.getId()).thenApply(partX -> {
item.setPartX(partX);
return item;
});
}
or, considering we don't care about the actual result type in fetchSingle():
public CompletableFuture<?> getPartXAndSetOnItem(Item item) {
return dao.getPartX(item.getId()).thenRun(item::setPartX);
}

Parsing from Json to Java Objects using GSON

I have JSON something lie that:
String json = "{'zadanie' : { "+
"'lista' : {" +
"'img': 'something.jpg'," +
"'opis': 'Prawdziwy minionek'," +
"'cena': 117.00," +
"'ilosc': 12," +
"'baza': ['truskawka - wanilia', 'sernik - pomarańcza', 'jagoda - wanilia', 'żurawina - wanilia', 'czekolada - wanilia', 'czekolada - banan', 'czekolada - cappuccino', 'tiramisu']," +
"'czas': '2 dni'"+
"}"+
"',lista2' : {" +
"'img': 'something2.jpg'," +
"'opis': 'Prawdziwy minionek'," +
"'cena': 117.00," +
"'ilosc': 12," +
"'baza': ['truskawka - wanilia', 'sernik - pomarańcza', 'jagoda - wanilia', 'żurawina - wanilia', 'czekolada - wanilia', 'czekolada - banan', 'czekolada - cappuccino', 'tiramisu']," +
"'czas': '2 dni'"+
"}"+
"]}}";
And I would like to parse it to object in Java. I have classes:
class Lista2{
private List<Lista> lista2;
public List<Lista> getLista2() {
return lista2;
}
public void setLista2(List<Lista> lista2) {
this.lista2 = lista2;
}
#Override
public String toString() {
return "GroupList{" + "lista2=" + lista2 + '}';
}}
//=================================================
class Lista {
private Data lista;
public Data getLista() {
return lista;
}
public void setLista(Data lista) {
this.lista = lista;
}
#Override
public String toString() {
return "Lista{" + "lista=" + lista + '}';
}}
//=================================================
class Data {
private String img;
private String opis;
private Double cena;
private Integer ilosc;
private List<String> baza;
private String czas;
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public Double getCena() {
return cena;
}
public void setCena(Double cena) {
this.cena = cena;
}
public Integer getIlosc() {
return ilosc;
}
public void setIlosc(Integer ilosc) {
this.ilosc = ilosc;
}
public List<String> getBaza() {
return baza;
}
public void setBaza(List<String> baza) {
this.baza = baza;
}
public String getCzas() {
return czas;
}
public void setCzas(String czas) {
this.czas = czas;
}
#Override
public String toString() {
return "Data{" + "img=" + img + ", opis=" + opis + ", cena=" + cena + ", ilosc=" + ilosc + ", baza=" + baza + ", czas=" + czas + '}';
} }
Something is wrong, because I have error: "StandardWrapperValve[Glowna]: Servlet.service() for servlet Glowna threw exception
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 360
at com.google.gson.Gson.fromJson(Gson.java:809)"
For GSON parse:
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(json));
reader.setLenient(true);
Lista2 userinfo1 = gson.fromJson(reader, Lista2.class);

Getting exception on PostUrlBuilder when build post URL for Volley Custom post request with array parameter with normal param

I am trying to build a post URL for Volley custom request to post some data to server using post method with normal param and array param. But I get some exception when build the post url for request. I am getting exception before make a request with volley custom request.
Map<String, String> params = new HashMap<>();
params.put(API.Parameter.ANDROID_DEVICE_ID, appManager.getDeviceId());
params.put(API.Parameter.ANDROID_APP_VERSION, appManager.getAppVersion());
params.put("trip_no", MainActivity.temp_trip_id);
Map<String, List<String>> arrayParams = new HashMap<>();
arrayParams.put("ticket_id",ticket_id);
arrayParams.put("ticket_name",ticket_name);
arrayParams.put("ticket_price_each",ticket_price_each);
PostUrlBuilder urlBuilder = new PostUrlBuilder(API.BOOK_TRIP_API_URL, params, arrayParams);
String Url = urlBuilder.getQueryUrl();
ObjectRequest<OnlineUserData> onlineUserDataObjectRequest = new ObjectRequest<OnlineUserData>(Request.Method.POST, Url, null,
new Response.Listener<OnlineUserData>() {
#Override
public void onResponse(OnlineUserData response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}, OnlineUserData.class);
AppController.getInstance().addToRequestQueue(onlineUserDataObjectRequest);
My PostUrlBuilder.java class is:
public class PostUrlBuilder {
private static final String TAG = PostUrlBuilder.class.getSimpleName();
private String url;
private Map<String, String> parameters;
private Map<String, List<String>> arrayParameters;
private String queryUrl;
public PostUrlBuilder() {
}
public PostUrlBuilder(String url, Map<String, String> parameters, Map<String, List<String>> arrayParameters) {
this.url = url;
this.parameters = parameters;
this.arrayParameters = arrayParameters;
buildQueryUrl();
}
public PostUrlBuilder(Map<String, String> parameters, String url) {
this.parameters = parameters;
this.url = url;
}
private void buildQueryUrl() {
StringBuilder urlBuilder = new StringBuilder(url);
if (parameters != null && parameters.size() != 0) {
urlBuilder.append("?");
int i = 0;
for (String key : parameters.keySet()) {
String value = parameters.get(key);
Log.d(TAG, "key= " + key + " & " + "value=" + value);
try {
urlBuilder.append(String.format("%s=%s", key, URLEncoder.encode(value, "UTf-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
i++;
if (i != parameters.size()) {
urlBuilder.append("&");
}
}
}
if (arrayParameters != null && arrayParameters.size() != 0) {
if (parameters != null && parameters.size() != 0) {
urlBuilder.append("&");
} else {
urlBuilder.append("?");
}
int i = 0;
for (String key : arrayParameters.keySet()) {
List<String> values = arrayParameters.get(key);
int j = 0;
for (String value : values) {
Log.d(TAG, "size = " + values.size() + " j = " + j + " key= " + key + " & " + "value=" + value);
try {
urlBuilder.append(String.format("%s[]=%s", key, URLEncoder.encode(value, "UTf-8")));
j++;
if (j != values.size()) {
urlBuilder.append("&");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
i++;
if (i != arrayParameters.size()) {
urlBuilder.append("&");
}
}
}
queryUrl = urlBuilder.toString();
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String> getParameters() {
return parameters;
}
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}
public String getQueryUrl() {
return queryUrl;
}
public void setQueryUrl(String queryUrl) {
this.queryUrl = queryUrl;
}
public Map<String, List<String>> getArrayParameters() {
return arrayParameters;
}
public void setArrayParameters(Map<String, List<String>> arrayParameters) {
this.arrayParameters = arrayParameters;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PostUrlBuilder)) return false;
PostUrlBuilder that = (PostUrlBuilder) o;
return this.getUrl().equals(that.getUrl())
&& this.getParameters().equals(that.getParameters())
&& this.getArrayParameters().equals(that.getArrayParameters())
&& this.getQueryUrl().equals(that.getQueryUrl());
}
#Override
public int hashCode() {
int result = getUrl().hashCode();
result = 31 * result + getParameters().hashCode();
result = 31 * result + getArrayParameters().hashCode();
result = 31 * result + getQueryUrl().hashCode();
return result;
}
#Override
public String toString() {
return "GetUrlBuilder{" +
"url='" + url + '\'' +
", parameters=" + parameters +
", queryUrl='" + queryUrl + '\'' +
'}';
}
}
I am getting exception in line below:
urlBuilder.append(String.format("%s[]=%s", key, URLEncoder.encode(value, "UTf-8")));
Error Log-cat shows errors below :
FATAL EXCEPTION: main
Process: com.shohoz.launch.cabin, PID: 12230
java.lang.NullPointerException
at libcore.net.UriCodec.encode(UriCodec.java:132)
at java.net.URLEncoder.encode(URLEncoder.java:57)
at com.shohoz.launch.cabin.toolbox.PostUrlBuilder.buildQueryUrl(PostUrlBuilder.java:70)
at com.shohoz.launch.cabin.toolbox.PostUrlBuilder.<init>(PostUrlBuilder.java:29)
at com.shohoz.launch.cabin.fragment.RightFullSeatLayoutFragment.onlineCreateAndInsertIntoConfirm(RightFullSeatLayoutFragment.java:1105)
at com.shohoz.launch.cabin.fragment.RightFullSeatLayoutFragment$15.onClick(RightFullSeatLayoutFragment.java:857)
at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:157)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5398)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:680)
at dalvik.system.NativeStart.main(Native Method)
Thanks in advance.
I've Figured out arrayParams.put("ticket_price_each",ticket_price_each); sending null value. That's why app was crashed.

Update text file method

I have a jtable that can be edite and then saved (updated) to a text file.
User select a line (that contains a book record) and request to borrow that book,
I use this method to update, But now when update, the old data is not deleted.
user_AllBooks uAllBooks = new user_AllBooks();
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == borrowButton) {
borrowInitialize(bTable.getSelectedRow());
}
public void borrowInitialize(int row) {
if (uAllBooks.getValueAt(row, 3).equals("Yes")) {
JOptionPane.showMessageDialog(null, "This Book Was Borrowed");
} else {
uAllBooks.setValueAt("Yes", row, 3);
uAllBooks.fireTableRowsUpdated(row, row);
uAllBooks.updateFiles(uAllBooks.bData);
}
}
...
}
public class user_AllBooks extends AbstractTableModel {
...
public void updateFiles(ArrayList<BookInformation> data) {
PrintWriter Bpw = null;
try {
Bpw = new PrintWriter(new FileWriter("AllBookRecords.txt" , true));
for (BookInformation bookinfo : data) {
String line = bookinfo.getBookID()
+ " " + bookinfo.getBookName()
+ " " + bookinfo.getBookDate()
+ " " + bookinfo.getBorrowStatus();
Bpw.println(line);
}
Bpw.close();
} catch (FileNotFoundException e1) {
} catch (IOException ioe) {
}
}
...
}
My BookInformation Class:
public class BookInformation {
private String BookName;
private String BookDate;
private String BookID;
private String BorrowStatus;
public String getBookName() {
return BookName;
}
public void setBookName(String book_name) {
this.BookName = book_name;
}
public String getBookDate() {
return BookDate;
}
public void setBookDate(String book_date) {
this.BookDate = book_date;
}
public String getBookID() {
return BookID;
}
public void setBookID(String Book_id) {
this.BookID = Book_id;
}
#Override
public String toString() {
return BookID + " " + BookName + " "
+ BookDate + " " + BorrowStatus + "\n";
}
public String getBorrowStatus() {
return BorrowStatus;
}
public void setBorrowStatus(String borrowStat) {
BorrowStatus = borrowStat;
}
}
Thanks.
Change this line
Bpw = new PrintWriter(new FileWriter("AllBookRecords.txt" , true));
to
Bpw = new PrintWriter(new FileWriter("AllBookRecords.txt" , false));
The second parameter (boolean) changes whether it should append the text file (add to the end of it) or just rewrite everything.
Source: Javadoc constructor summary for FileWriter:
FileWriter(String fileName, boolean append)
Constructs a FileWriter object given a file name with a boolean
indicating whether or not to append the data written.

Trying to make use of Akka future and play promises in my Play2 application

When reading up on the play2 documentation I found this:
Because of the way Play 2.0 works, action code must be as fast as
possible (i.e. non blocking). So what should we return as result if we
are not yet able to compute it? The response should be a promise of a
result!
Wow! This of course made me interested in playakka and akka.
I'm currently building an autocomplete application that is integrating with elasticsearch,
so this would be a perfect fit!
Controller:
public class AutoComplete extends Controller {
#BodyParser.Of(value = BodyParser.Json.class)
public static Result complete(final String term) {
F.Promise<List<String>> list = Akka.future(new Callable<List<String>>() {
public List<String> call() throws Exception {
List<String> list = IndexService.find(term);
return list;
}
});
return async(list.map(new F.Function<List<String>, Result>() {
#Override
public Result apply(List<String> list) throws Throwable {
return ok(Json.toJson(list));
}
}));
}
Service:
public static List<String> find(final String term) {
IndexQuery < SearchWord > query = SearchWord.find.query();
query.setQuery("{\n" +
" \"bool\": {\n" +
" \"should\": [\n" +
" {\n" +
" \"text\": {\n" +
" \"search_word.ngrams\": {\n" +
" \"operator\": \"and\",\n" +
" \"query\": \""+term+"\"\n" +
" }\n" +
" }\n" +
" },\n" +
" {\n" +
" \"text\": {\n" +
" \"search_word.full\": {\n" +
" \"boost\": 1,\n" +
" \"query\": \""+term+"\"\n" +
" }\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
"}");
IndexResults<SearchWord> indexResults = SearchWord.find.search(query);
List<String> list = new ArrayList<String>();
for(SearchWord word : indexResults.getResults()){
list.add(word.getWord());
}
return list;
}
}
SearchWord:
#IndexType(name = "search_word")
public class SearchWord extends Index {
// Find method static for request
public static Index.Finder<SearchWord> find = new Index.Finder<SearchWord>(SearchWord.class);
public enum WordType {
NAME,
STRONG_SEARCH_WORD,
WEAK_SEARCH_WORD,
BANNED
}
private String word;
private WordType wordType;
public SearchWord() {
}
public SearchWord(IndexWord indexWord) {
super.id = ""+indexWord.getId();
this.word = StringUtils.lowerCase(indexWord.getWord());
this.wordType = WordType.valueOf(indexWord.getType());
}
public String getId() {
return super.id;
}
public void setId(String id) {
super.id = id;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public WordType getWordType() {
return wordType;
}
public void setWordType(WordType wordType) {
this.wordType = wordType;
}
#Override
public Map toIndex() {
HashMap map = new HashMap();
map.put("id", super.id);
map.put("word", word);
map.put("word_type", wordType.toString());
return map;
}
#Override
public Indexable fromIndex(Map map) {
if (map == null) {
return this;
}
this.word = (String) map.get("word");
this.wordType = WordType.valueOf((String)map.get("word_type"));
return this;
}
}
The code works very well but I must say that I'm not that sure that I have implemented this correctly. I'm really struggling to understand the documentation.
So my questions are basically:
Have I implemented the Future and Promise correctly?
Would it be better to create a custom actor, and in that actor perform the index
search, like the example in the docs:
=====
return async(
Akka.asPromise(ask(myActor,"hello", 1000)).map(
new Function<Object,Result>() {
public Result apply(Object response) {
return ok(response.toString());
}
}
)
);
Maybe you have some great example that I have not found yet?
AFAIK, your code is totally ok.
I may be wrong, but I think that the second option is strictly equivalent to the first one, since the Akka.future() method is a wrapper around the Akka.promise() method.
From the Akka class source code of Play 2.0.4:
/**
* Executes a block of code asynchronously in the application Akka Actor system.
*/
public static <T> Promise<T> future(java.util.concurrent.Callable<T> callable) {
return asPromise(akka.dispatch.Futures.future(callable, system().dispatcher()));
}
Although you have correctly implemented the Promise and Future, i wouldn't consider this code to be "non-blocking"...
It seems that the blocking call is
List<String> list = IndexService.find(term);
and although this is now wrapped in a promise/future, it is still a blocking call...
If you want to be truly non-blocking (with all its benefits), you'll have to make your data access (queries) non-blocking...
Oh, and a non-blocking action method should return a Promise of a Result, not a Result...
This is how i should write your code:
#BodyParser.Of(value = BodyParser.Json.class)
public static F.Promise<Result> complete(final String term) {
scala.concurrent.Future<List<String>> listFuture = IndexService.find(term);
F.Promise<List<String>> listPromise = F.Promise.wrap(listFuture);
return listPromise.map(new F.Function<List<String>, Result>() {
#Override
public Result apply(List<String> list) throws Throwable {
return ok(Json.toJson(list));
}
});
}
Hope this helps!

Categories