i tried to post data to api with khttp but there is an error
this is my code
val payload = mapOf("review" to addReviewET.text, "rating" to quantity.toString(), "id_user" to "1", "id_movie" to id)
val r = post(localhost.insertReview(), data = payload)
println(r.text)
but it doesn't work it says error like this
FATAL EXCEPTION: main
Process: com.mqa.android.moviereview, PID: 23984
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
at java.net.SocketInputStream.read(SocketInputStream.java:169)
at java.net.SocketInputStream.read(SocketInputStream.java:139)
at com.android.okhttp.okio.Okio$2.read(Okio.java:136)
at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at com.android.okhttp.okio.RealBufferedSource.exhausted(RealBufferedSource.java:60)
at com.android.okhttp.internal.io.RealConnection.isHealthy(RealConnection.java:361)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:137)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258)
at khttp.responses.GenericResponse$Companion$defaultEndInitializers$1.invoke(GenericResponse.kt:90)
at khttp.responses.GenericResponse$Companion$defaultEndInitializers$1.invoke(GenericResponse.kt:32)
at khttp.responses.GenericResponse$connection$2.invoke(GenericResponse.kt:164)
at khttp.responses.GenericResponse$connection$2.invoke(GenericResponse.kt:30)
at khttp.responses.GenericResponse.openRedirectingConnection$khttp(GenericResponse.kt:124)
at khttp.responses.GenericResponse.getConnection(GenericResponse.kt:163)
at khttp.responses.GenericResponse.getRaw(GenericResponse.kt:207)
at khttp.responses.GenericResponse.getContent(GenericResponse.kt:216)
at khttp.responses.GenericResponse.init$khttp(GenericResponse.kt:350)
at khttp.KHttp.request(KHttp.kt:59)
at khttp.KHttp.post(KHttp.kt:48)
at khttp.KHttp.post$default(KHttp.kt:47)
at com.mqa.android.moviereview.module.activity.AddActivity$showMovieList$3.invokeSuspend(AddActivity.kt:90)
at com.mqa.android.moviereview.module.activity.AddActivity$showMovieList$3.invoke(Unknown Source:40)
at org.jetbrains.anko.sdk27.coroutines.Sdk27CoroutinesListenersWithCoroutinesKt$onClick$1$1.invokeSuspend(ListenersWithCoroutines.kt:300)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask$DefaultImpls.run(Dispatched.kt:235)
at kotlinx.coroutines.DispatchedContinuation.run(Dispatched.kt:81)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
what is this error exactly? and how to make it right? or if you have other way please let me know. thank you
i got the way from here
The issue is that you want to run the http request on the main thread.
There are two way to avoid this error.
Disable strict mode, which means you can run the request on the main thread.
Make the request with AsyncTask. This is the recommended way, however it involves some job to do and look for the results by having the app state under control.
Related
Suppose I need to send a large amount of data from the client to the server using python gRPC. And I want to continue the rest computation when sending the message out instead of blocking the code. Is there any way can implement this?
I will illustrate the question by an example using the modified code from the greeter_client.py
for i in range(5):
res=computation()
response = stub.SayHello(helloworld_pb2.HelloRequest(data=res))
I want the computation of the next iteration continue while sending the "res" of last iteration. To this end, I have tried the "async/await", which looks like this
async with aio.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
for j in range(5):
res=computation()
response = await stub.SayHello(helloworld_pb2.HelloRequest(data=res))
But the running time is actually the same with the version without async/await. The async/await does not work. I am wondering is there anything wrong in my codes or there are other ways?
Concurrency is different than parallelism. AsyncIO allows multiple coroutines to run on the same thread, but they are not actually computed at the same time. If the thread is given a CPU-heavy work like "computation()" in your snippet, it doesn't yield control back to the event loop, hence there won't be any progress on other coroutines.
Besides, in the snippet, the RPC depends on the result of "computation()", this meant the work will be serialized for each RPC. But we can still gain some concurrency from AsyncIO, by handing them over to the event loop with asyncio.gather():
async with aio.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
async def one_hello():
res=computation()
response = await stub.SayHello(helloworld_pb2.HelloRequest(data=res))
await asyncio.gather(*(one_hello() for _ in range(5)))
I am implementing a gen_fsm using the gen_statem module and when i am trying to check its state as a handle_event_function i get the following error:
> ** exception error: {function_clause,
> {gen_statem,call,[{ok,<0.139.0>},state,0]}}
> in function gen:do_for_proc/2
> called as gen:do_for_proc({ok,<0.139.0>},#Fun<gen.0.9801092>)
> in call from gen_statem:'-call_clean/4-fun-0-'/5 (gen_statem.erl, line 637) 25> c("C:/Erlang/Genserv/fsm.erl").
Below is my code which is separated into :
-mandatory methods for the fsm to work
-api that the client can use (state change,get the state,start)
- generic handlers for when client demands something related to state
-state implementations
Module
-module(fsm).
-record(state,{
current="None",
intvCount=0,
jobCount=0
}).
-export([init/1,terminate/3,callback_mode/0,code_change/4]).
-export([state/1,start/0,hire/2,fire/2,interview/2]).
-export([sitting_home/3,interviewing/3,working/3]).
-behaviour(gen_statem).
%API
start()->
gen_statem:start_link(?MODULE,[],[]).
state(PID)->
gen_statem:call(PID,state,0).
hire(PID,Company)->
gen_statem:call(PID,{hire,Company},0).
fire(PID,Company)->
gen_statem:call(PID,{fire,Company},0).
interview(PID,Company)->
gen_state:call(PID,{intv,Company},0).
%mandatory
code_change(V,State,Data,Extra)->{ok,State,Data}.
callback_mode() ->
[state_functions,handle_event_function].
init([])->
{ok,sitting_home,#state{current="None",jobCount=0,intvCount=0}}.
terminate(Reasom,State,Data)->
void.
% Generic handlers
handle_event({call,From},state,State)->
{keep_state,State,[{reply,From,State}]};
handle_event(_,_,State)->
{keep_state,State}.
% State implementations
sitting_home({call,From},{intv,Company},State=#state{intvCount=C})->
{next_state,interviewing,State#state{intvCount=C+1},[{reply,From,"Interviewing by:"++Company}]};
sitting_home(EventType,Event,State)->
handle_event(EventType,Event,State).
interviewing({call,From},{rejected,Company},State)->
{next_state,sitting_home,State,[{reply,From,"rejected by:"++Company}]};
interviewing({call,From},{accepted,Company},State=#state{jobCount=J})->
{next_state,
working,
State#state{jobCount=J+1,current=Company},
[{reply,From,"accepted offer from:"++Company}]
};
interviewing(EventType,Event,State)->
handle_event(EventType,Event,State).
working({call,From},{fire,Company},State=#state{current=C})->
{next_state,working,State#state{current="None"},[{reply,From,"Got fired from"++Company}]};
working(EventType,Event,State)->
handle_event(EventType,Event,State).
Usage
FSM_PID=fsm:start().
fsm:state(PID). //crashes when demanding state
fsm:hire(PID,"Some Company").
fsm:start() returns the tuple {ok,Pid}. You cannot use directly the return of the function in your next call. Instead you must do something like:
{ok,P} = fsm:start().
fsm:state(P).
Then you will experience other troubles, the first one is that you specify a timeout of 0, so you will get a timeout error. You will have to change this, and continue debugging :o)
[edit]
You don't need to specify the Pid, it is done in background by the gen_statem code, the gen_statem:call function is executed in the caller context so it still has access to the caller Pid.
In fact it is a little more complex, depending if you specify a timeout or not, the gen_statem:call/3 will spawn a process to call the gen:call/4 function or will directly call it, thus the Pid sent to the state machine will be either the spawned function's one or the caller's one.
The gen:call/4 also add a Reference in the message to the state machine to "sign" the answer and guaranty that an incoming message from any other part of the application will not be interpreted as the answer.
This is a general pattern in erlang (and programming) to hide as much as possible the system mechanism in interface function. Just as you do in the function state/1
Hello i am trying to figure out when using the gen_statem why do the calls block,since my fsm is running in a separate process.
-module(fsm).
-record(data,{
current="None",
intvCount=0,
jobCount=0
}).
-export([init/1,terminate/3,callback_mode/0,code_change/4]).
-export([state/1,start/0,interview/2,reject/2,wait/1]).
-export([sitting_home/3,interviewing/3]).
-export([handle_event/3]).
-behaviour(gen_statem).
handle_event({call,From},get_state,Data)->
io:format("why you need state>"),
{keep_state,Data};
handle_event({call,From},Event,Data)->
{keep,state,Data}.
%API
start()->
gen_statem:start_link(?MODULE,[],[]).
state(PID)->
gen_statem:call(PID,get_state).
interview(PID,Company)->
gen_statem:call(PID,{intv,Company}).
reject(PID,Company)->
gen_statem:call(PID,{reject,Company}).
wait(PID)->
gen_statem:call(PID,{wait}).
%mandatory
code_change(V,State,Data,Extra)->{ok,State,Data}.
callback_mode() ->
state_functions.
init([])->
{ok,sitting_home,#data{current="None",jobCount=0,intvCount=0}}.
terminate(Reasom,State,Data)->
void.
% State implementations
sitting_home({call,From},{intv,Company},Data=#data{intvCount=C})->
io:format("called for interview"),
{next_state,interviewing,Data#data{intvCount=C+1},{reply,From,something}};
sitting_home({call,From},Event,Data)->
{keep_state,Data}.
interviewing({call,From},{rejected,Company},Data)->
{next_state,sitting_home,Data,{reply,From,somethingelse}};
interviewing({call,From},wait,Data)->
{keep_state,Data}.
Usage:
>{ok,Pid}=fsm:start().
>fsm:state(). //blocks !
>{ok,Pid}=fsm:start().
>fsm:interview(Pid).
called for interview %and blocks
Why do both calls block? I am spawning a different process besides the shell in which the fsm runs using the gen_statem:start_link.
Why in both cases it blocks?
Update
I have updated my post after i was pointed out that i forgot to use reply in order to send something back to the caller.However the handle_event/3 still blocks even in this form:
handle_event({call,From},get_state,Data)->
{keep_state,Data,[{reply,From,Data}]}.
Because that's what gen_statem:call does:
Makes a synchronous call to the gen_statem ServerRef by sending a request and waiting until its reply arrives
and your state functions don't send any replies. They should look like
sitting_home({call,From},{intv,Company},Data=#data{intvCount=C})->
io:format("called for interview"),
{next_state,interviewing,Data#data{intvCount=C+1},{reply,From,WhateverReplyYouWant}};
or
sitting_home({call,From},{intv,Company},Data=#data{intvCount=C})->
io:format("called for interview"),
gen_statem:reply(From, WhateverReplyYouWant),
{next_state,interviewing,Data#data{intvCount=C+1}};
If there's no useful reply, consider
using cast instead of call (and handling cast as the EventType in your state functions), or
ok as the reply.
I have created a simple Kafka consumer that returns a Flux of objects (the received messages) and I'm trying to test it using the StepVerifier.
In my test, I do something like that:
Flux<Pojo> flux = consumer.start();
StepVerifier.create(flux)
.expectNextMatches(p -> p.getList().size() == 3)
.verifyComplete();
The assertion works ok (if I change the value from 3 to something else, the test fails). But, if the assertion passes, than the test never exit.
I have also tried to use the verify method like so:
StepVerifier.create(flux)
.expectNextMatches(f -> f.getEntitlements().size() == 3)
.expectComplete()
.verify(Duration.ofSeconds(3));
In this case, I get this error:
java.lang.AssertionError: VerifySubscriber timed out on false
Any idea what I'm doing wrong?
The Kafka Flux is probably infinite, so it never emits the onComplete signal, which the test waits for. You can call .thenCancel().verify() if you're only interested in testing that first value.
So I am currently working with the ZenDesk API. I am creating many users using the batch CreateUser method that takes an array of up to 100 user objects. Now, for some reason, some users fail to generate. Therefore, I wanted to obtain the result of the JobStatus after creating the users so that I can identify the problem easily. The issue is that the result variable is null after performing the CreateUsers() method.
Some sample code:
public static void createEndUsers(Zendesk zd){
for(Organization org : zd.getOrganizations()){
List<User> usersList = getUsersPerOrg(org, 0)
JobStatus js = zd.createUsers(usersList);
List<T> resultElements = js.getResults();
}
}
Why is getResults() returning null in this instance? Is it because the operation has not yet been performed when it reaches that part of the code? How can I make sure that I "wait" until the result is ready before I try to access it?
If you have a look at the posssible values from org.zendesk.client.v2.model.JobStatus.JobStatusEnum you will notice that the job may be queued for execution or it could still be running at the time that the job status was returned by the operation org.zendesk.client.v2.Zendesk#createUsers(org.zendesk.client.v2.model.User...).
As can be seen from the Zendesk Documentation for createUsers Operation
This endpoint returns a job_status JSON object and queues a background job to do the work. Use the Show Job Status endpoint to check for the job's completion.
only when the job is completed, there will be a corresponding result delivered for the operation.
A possible solution in your case would be to check (possibly in a separate thread) every 500ms whether the job status is not queued or not running (otherwise said whether it completed) and if it successfully completed to retrieve the results.