gRPC UNAVAILABLE EOF Error while waiting for data - java

I'm trying to create a Java version of jtimon Github
On Github you can see the proto message for defining the service
And my Java code looks like following
package jti.collector;
public class JTICollector {
private static final Logger log = LoggerFactory.getLogger(JTICollector.class);
private static final String DEVICE_ADDRESS = "100.96.244.41";
private static final int GRPC_PORT = 50051;
private static final int SAMPLE_FRQ = 2000;
private static final long SLEEP_TIME = 10000;
private static final long SLEEP_TIME_FOR_REQ = 10;
public static void main(final String[] args) {
final String username = "AAA";
final String password = "BBB";
log.info("UserName : " + username);
final ManagedChannel channel = ManagedChannelBuilder
.forAddress(DEVICE_ADDRESS, GRPC_PORT)
.usePlaintext(true)
.build();
LoginGrpc.LoginBlockingStub loginStub = LoginGrpc.newBlockingStub(channel);
Authentication.LoginRequest loginRequest = Authentication.LoginRequest.newBuilder()
.setClientId("foo-bar")
.setUserName(username)
.setPassword(password)
.build();
Authentication.LoginReply loginReply = loginStub.withDeadlineAfter(SLEEP_TIME_FOR_REQ, TimeUnit.SECONDS)
.loginCheck(loginRequest);
log.info("LoginReply : " + loginReply.toString());
OpenConfigTelemetryGrpc.OpenConfigTelemetryStub stub = OpenConfigTelemetryGrpc.newStub(channel);
Telemetry.SubscriptionRequest request = Telemetry.SubscriptionRequest.newBuilder()
.addPathList(Telemetry.Path.newBuilder()
.setPath("/interfaces")
.setSampleFrequency(SAMPLE_FRQ) //In mills
.build())
.build();
final CountDownLatch finishLatch = new CountDownLatch(1);
StreamObserver<Telemetry.OpenConfigData> responseObserver = new StreamObserver<Telemetry.OpenConfigData>() {
#Override
public void onNext(final Telemetry.OpenConfigData value) {
log.info("Received Value : " + value.toString());
}
#Override
public void onError(final Throwable t) {
log.warn("onError", t);
finishLatch.countDown();
}
#Override
public void onCompleted() {
log.info("onCompleted");
finishLatch.countDown();
}
};
stub.telemetrySubscribe(request, responseObserver);
log.info("Blocking on latch");
try {
finishLatch.await();
} catch (InterruptedException e) {
log.warn("Finnish Latch Failed", e);
}
}
}
Login get success. But onNext() never get called. And the onError() trigger with a message including some of the content which im looking for
io.grpc.StatusRuntimeException: UNAVAILABLE: {"created":"#1511903558.423607783","description":"EOF","file":"../../../../../../../../src/dist/grpc/src/core/lib/iomgr/tcp_posix.c","file_line":235,"grpc_status":14}i-safi-nameRIPV4_UNICAST:B
>afi-safis/afi-safi[afi-safi-name='IPV4_UNICAST']/state/enabledH:A
=afi-safis/afi-safi[afi-safi-name='IPV4_UNICAST']/state/activeH
at io.grpc.Status.asRuntimeException(Status.java:526)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:418)
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:663)
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:392)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:443)
at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:63)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:525)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$600(ClientCallImpl.java:446)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:557)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

See here for more information https://github.com/grpc/grpc-java/issues/3800
In summary the problem was; the grpc server was failing to parse a tracing related header in the request. But there was no public interface in the client to turn it off.

Related

How can I configure jcabi-aspect to NOT print method return value?

I have a class that has #Loggable(DEBUG) which prints return value of public method like this:
class:
#Loggable(DEBUG)
public class FhirAccessTokenServiceImpl implements FhirAccessTokenService {
private static final Logger LOG = LoggerFactory.getLogger(FhirAccessTokenServiceImpl.class);
private static final String ACCESS_TOKEN_FIELD = "access_token";
private static final Integer RETRY_COUNT = 3;
private final String loginUrl;
#Override
public String getToken(ServerCredential<FhirServer> serverCredential) throws HealthDataConnectorServiceException {
try {
WebClient client = WebClient.create(String.format(loginUrl,
serverCredential.getServer().getAzureTenantId()));
return client.post()
.accept(MediaType.APPLICATION_FORM_URLENCODED)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(this.getFormInserter(serverCredential))
.retrieve()
.bodyToMono(String.class)
.retry(RETRY_COUNT)
.map(this::getToken)
.block();
} catch (WebClientException | JsonParseException e) {
throw new HealthDataConnectorServiceException(String.format("Error occurred while getting token for " +
"fhir url: %s", serverCredential.getServer().getServerUrl()), e);
}
}
and here is the log in AKS:
[HDC-FhirBundle]] n.p.d.h.c.s.i.FhirAccessTokenServiceImpl : #getToken('ServerCredential [server=FhirServer [fhirVersion=..354..'2022-12-19', lastModified='2022-12-19']]]'): 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..1192..eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 141.88ms
(I modified 'eyaaaa... ' due to sensitive information)
How can I configure jcabi-aspects to NOT print this secret(token)?

software.amazon.awssdk.services.s3.model.S3Exception: Invalid response status from request while using aws java sdk v2 "S3TRANSFERMANAGER"

am trying to use S3TransferManager to upload file to s3. but my unit test fails due to the below error,
java.util.concurrent.CompletionException: software.amazon.awssdk.services.s3.model.S3Exception: Invalid response status from request
here's my code,
public class AwsTransferService {
private final S3TransferManager s3TransferManager;
private final AwsS3Config s3Config;
public AwsTransferService(AwsS3Config s3Config, AwsConfig awsConfig) {
this.s3Config = s3Config;
AwsBasicCredentials awsCredentials = create(awsConfig.getAccessKey(), awsConfig.getSecretKey());
this.s3TransferManager = S3TransferManager.builder()
.s3ClientConfiguration(builder -> builder.credentialsProvider(create(awsCredentials))
.region(s3Config.getRegion())
.minimumPartSizeInBytes(10 * MB)
.targetThroughputInGbps(20.0))
.build();
}
public AwsTransferService(S3TransferManager s3TransferManager, AwsS3Config s3Config) {
this.s3TransferManager = s3TransferManager;
this.s3Config = s3Config;
}
public void transferObject(#NonNull String bucketName, #NonNull String transferKey, #NonNull File file) {
validateS3Key(transferKey);
validatePath(file.toPath());
log.info("Transfering s3 object from :{} to :{}", file.getPath(), transferKey);
try {
Upload upload =
s3TransferManager.upload(b -> b.putObjectRequest(r -> r.bucket(bucketName).key(transferKey))
.source(file.toPath()));
CompletedUpload completedUpload = upload.completionFuture().join();
log.info("PutObjectResponse: " + completedUpload.response());
} catch (Exception e) {
e.printStackTrace();
}
}
and here is my unit test for the above code,
#RegisterExtension
public static final S3MockExtension S3_MOCK = builder()
.silent()
.withSecureConnection(false)
.build();
private S3ClientConfiguration s3ClientConfiguration;
private AwsTransferService service;
private AwsS3Service awsS3Service;
private S3TransferManager s3TransferManager;
private static S3Client s3Client;
#BeforeAll
public static void beforeAll() {
s3Client = S3_MOCK.createS3ClientV2();
}
#BeforeEach
public void beforeEach() throws IOException {
s3ClientConfiguration =mock(S3ClientConfiguration.class);
s3TransferManager = S3TransferManager.builder().s3ClientConfiguration(s3ClientConfiguration).build();
AwsS3Config s3Config = AwsS3Config.builder()
.region(Region.AP_SOUTHEAST_2)
.s3BucketName(S3Factory.VALID_S3_BUCKET)
.build();
awsS3Service = new AwsS3Service(s3Config, s3Client);
awsS3Service.createBucket(VALID_S3_BUCKET);
service = new AwsTransferService(s3TransferManager, s3Config);
}
#Test
public void transferObject_singleFile_ShouldUploadFiletoS3() throws IOException {
String transferKey = TRANSFER_KEY_UPLOAD;
String fileName = FILE_PATH + TRANSFER_FILE_NAME;
writeFile(fileName);
File transferFile = new File(fileName);
service.transferObject(VALID_S3_BUCKET, transferKey + TRANSFER_FILE_NAME, transferFile);
int expectedObjectsSize = 1;
Log.initLoggingToFile(Log.LogLevel.Error, "log.txt");
List<S3Object> matchedObjects = awsS3Service.listObjectsWithPrefix(transferKey + TRANSFER_FILE_NAME);
assertEquals(expectedObjectsSize, matchedObjects.size());
assertEquals(transferKey + TRANSFER_FILE_NAME, matchedObjects.get(0).key());
}
please let me know why the unit test fails with the above mentioned error?
also please let me know is there any other way to mock "s3ClientConfiguration"? in aws java sdk v2

Can I clean the value of the map in the Netty's ChannelHandler with a periodic timer task?

I define a schedule task in the main thread, I want to clean the value of the map which caches my project's client information in ChannelHandler. But it doesn't work. What did I do wrong?
This is main app code where I schedule a task.
public class Server {
public static void main(String[] args) throws Exception {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
final ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
ServerBootstrap b = new ServerBootstrap();
//init() code Omitted
ScheduledFuture<?> sf = ctx.executor().scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
HashSet<String> clients = new HashSet<>();
Map<String,String> map = LoginAuthRespHandler.getNodeCheck();
System.out.println(map.size());
for (String key:map.keySet()) {
clients.add(map.get(key));
}
try{
//doSomething();
}catch (Exception e){
e.printStackTrace();
}
map.clear();
clients.clear();
}
},10,10,TimeUnit.SECONDS);
ChannelFuture cf = b.bind(NettyConstant.REMOTEIP,NettyConstant.PORT).sync();
System.out.println("Netty server start ok on: "
+ (NettyConstant.REMOTEIP + " : " + NettyConstant.PORT));
cf.channel().closeFuture().sync();
work.shutdownGracefully();
boss.shutdownGracefully();
}
}
And this is the ChannelHandler code.
public class LoginAuthRespHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(LoginAuthRespHandler.class);
private static Map<String, String> nodeCheck = new ConcurrentHashMap<String, String>();
private String[] whiteList = { "127.0.0.1", "192.168.56.1" };
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
AlarmMessage message = (AlarmMessage) msg;
if (message.getHeader() != null && message.getHeader().getType() == MessageType.LOGIN_REQ.value()) {
String nodeIndex = ctx.channel().remoteAddress().toString();
AlarmMessage loginResp = null;
if (nodeCheck.containsKey(nodeIndex)) {
loginResp = buildResponse(ResultType.FAIL);
} else {
InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
String ip = address.getAddress().getHostAddress();
boolean isOK = false;
for (String WIP : whiteList) {
if (WIP.equals(ip)) {
isOK = true;
break;
}
}
loginResp = isOK ? buildResponse(ResultType.SUCCESS) : buildResponse(ResultType.FAIL);
if (isOK)
//add a client value to the map
nodeCheck.put(nodeIndex, message.getBody().toString());
}
ctx.writeAndFlush(loginResp);
} else {
ctx.fireChannelRead(msg);
}
}
private AlarmMessage buildResponse(ResultType result) {
AlarmMessage message = new AlarmMessage();
Header header = new Header();
header.setType(MessageType.LOGIN_RESP.value());
message.setHeader(header);
message.setBody(result.value());
return message;
}
#Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String nodeIndex = ctx.channel().remoteAddress().toString();
ctx.close();
if(nodeCheck.containsKey(nodeIndex)){
nodeCheck.remove(nodeIndex);
}
}
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
//nodeCheck.remove(ctx.channel().remoteAddress().toString());
ctx.close();
ctx.fireExceptionCaught(cause);
}
public synchronized static Map<String, String> getNodeCheck() {
return nodeCheck;
}
}

Combine to JSON HTTP POST requests?

I am a starting programmer, and for school I have to make a servlet, and an Android app.
A server sends a request to my servlet with JSON like this:
{
"function":"authenticate",
"requestId":"[random]",
"deviceId":"[android deviceid]",
"serviceType":"GCM"
}
The servlet reads the JSON and uses authenticateRequest() to send the notification:
else if(function.equals("authenticate"))
{
// Get the deviceId
String deviceId = jsonRequest.getDeviceId();
// Get the serviceType
String serviceType = jsonRequest.getServiceType();
GCM gcmClass = new GCM();
// Send authentication request to the user
int authenticationResult = 0;
if(serviceType.equals("GCM"))
{
authenticationResult = gcmClass.authenticateRequest(deviceId, requestId);
}
if(serviceType.equals("APNS"))
authenticationResult = 70000;
// Set the result field
jsonResponse.setResult(authenticationResult);
// Set the result text
if(authenticationResult == 0)
{
jsonResponse.setResultText("OK");
}
else if(serviceType.equals(10000))
{
jsonResponse.setResultText("DENY");
}
else if(serviceType.equals(70000))
{
jsonResponse.setResultText("Unsupported");
}
else
{
jsonResponse.setResult(50000);
}
// Set the requestId field
jsonResponse.setRequestId(requestId);
// Send the JSON response
response.getOutputStream().print(gson.toJson(jsonResponse));
response.getOutputStream().flush();
}
authenticateRequest (at this point it always says status 0 (which means always ALLOW):
public int authenticateRequest(String regId, String requestId)
{
try
{
String messageText = "New authentication request received!";
Sender sender = new Sender(Config.GOOGLE_SERVER_KEY);
Message message = new Message.Builder().timeToLive(30).delayWhileIdle(true).addData(Config.MESSAGE_KEY, messageText).addData("requestid", requestId).build();
result = sender.send(message, regId, 1);
return 0;
}
catch(Exception e) {
e.printStackTrace();
return 60000;
}
}
Now the Android app receives the requestId and I am able to use that to send another JSON HTTP POST request to the servlet.
The android app needs to send an ALLOW of DENY to the servlet and the servlet should return that in the same session as the first request was received.
But I can't seem to figure out how to do this, been stuck at this point a couple of days now.
I would be very grateful is someone could help me with this.
I found the answer myself! :D
This is what I was looking for:
class Authenticate {
boolean flag = true;
String finalUserInput = null;
public synchronized String sendAuthentication(String deviceId, String requestId)
{
// Send notification
GCM gcmClass = new GCM();
gcmClass.authenticateRequest(deviceId, requestId);
while(flag)
{
try
{
wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = true;
notify();
return finalUserInput;
}
public synchronized void receiveAuthentication(String userInput, String requestId) {
finalUserInput = userInput;
flag = false;
notify();
}
}
class T1 implements Runnable {
Authenticate m;
private final String deviceId;
private final String requestId;
String result;
public T1(Authenticate m1, String deviceId, String requestId)
{
this.m = m1;
this.deviceId = deviceId;
this.requestId = requestId;
Thread t1 = new Thread(this, "sendAuthentication");
t1.start();
// Wait for thread to finish before sending response
try
{
t1.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public void run()
{
result = m.sendAuthentication(deviceId, requestId);
}
public String getResult(){
return result;
}
}
class T2 implements Runnable {
Authenticate m;
private final String requestId;
private final String userInput;
public T2(Authenticate m2, String requestId, String userInput) {
this.m = m2;
this.requestId = requestId;
this.userInput = userInput;
Thread t2 = new Thread(this, "receiveAuthentication");
t2.start();
}
public void run() {
m.receiveAuthentication(userInput, requestId);
}
}
public class AuthenticationHandler {
final static Authenticate m = new Authenticate();
public static String sendRequest(String deviceId, String requestId)
{
T1 runnable = new T1(m, deviceId, requestId);
String result = runnable.getResult();
return result;
}
public static void receiveResponse(String requestId, String userInput)
{
new T2(m, requestId, userInput);
}
}

playframework-2.3 Akka-Async interaction porting?

I have some old playframework 2.2 java webservice that interacts with akka, and now I should port them to playframework 2.3.
However, async has been deprecated and even after reading the doc about the async porting (http://www.playframework.com/documentation/2.3.x/JavaAsync) I wasn't able to understand how to apply it to my case (code below):
I must make the await for a timeout/akka server reply before starting the construction of my reply (ok()), otherwise I will block the thread.
I should make the actorselection async too.
I should make the akka server reply parsing/reply construction async too
I looked around and I wasn't able to find an example of such interactions, even in typesafe templates.
How could I do that?
/* playframework 2.2 code */
public class Resolve extends Controller {
private final static String RESOLVER_ACTOR = play.Play.application().configuration().getString("actor.resolve");
#CorsRest
#VerboseRest
#RequireAuthentication
#BodyParser.Of(BodyParser.Json.class)
public static Result getJsonTree() {
JsonNode json = request().body().asJson();
ProtoBufMessages.ResolveRequest msg;
ResolveRequestInput input;
try {
input = new ResolveRequestInput(json);
} catch (rest.exceptions.MalformedInputException mie) {
return badRequest(mie.getMessage());
}
msg = ((ProtoBufMessages.ResolveRequest)input.getMessage());
ActorSelection resolver = Akka.system().actorSelection(RESOLVER_ACTOR);
Timeout tim = new Timeout(Duration.create(4, "seconds"));
Future<Object> fut = Patterns.ask(resolver, input.getMessage(), tim);
return async (
F.Promise.wrap(fut).map(
new F.Function<Object, Result>() {
public Result apply(Object response) {
ProtoBufMessages.ResolveReply rsp = ((ProtoBufMessages.ResolveReply)response);
ResolveOutput output = new ResolveOutput(rsp);
return ok(output.getJsonReply());
}
}
)
);
}
}
I came out with the code below
public class Resolve extends Controller {
private final static String RESOLVER_ACTOR = play.Play.application().configuration().getString("actor.resolve");
private final static BrainProtoMessages.ResolveReply request_error = BrainProtoMessages.ResolveReply.newBuilder()
.setReturnCode(BResults.REQUEST_FAILED)
.build();
#CorsRest
#VerboseRest
#RequireAuthentication
#BodyParser.Of(BodyParser.Json.class)
public static Result resolve_map() {
final ResolveRequestInput input;
final F.Promise<ActorSelection> selected_target;
final F.Promise<Future<Object>> backend_request;
final F.Promise<BrainProtoMessages.ResolveReply> backend_reply;
final F.Promise<ObjectNode> decode_json;
final F.Promise<Result> ok_result;
final JsonNode json = request().body().asJson();
try {
input = new ResolveRequestInput(json);
} catch (rest.exceptions.MalformedInputException mie) {
return badRequest(mie.getMessage());
}
selected_target = F.Promise.promise(
new F.Function0<ActorSelection>() {
#Override
public ActorSelection apply() throws Throwable {
return Akka.system().actorSelection(RESOLVER_ACTOR);
}
}
);
backend_request =
selected_target.map(
new F.Function<ActorSelection, Future<Object>>() {
#Override
public Future<Object> apply(ActorSelection actorSelection) throws Throwable {
return Patterns.ask(actorSelection, input.getMessage(),new Timeout(Duration.create(4, "seconds")));
}
}
);
backend_reply = backend_request.map(
new F.Function<Future<Object>, BrainProtoMessages.ResolveReply>() {
#Override
public BrainProtoMessages.ResolveReply apply(Future<Object> akka_reply) throws Throwable {
try {
return (BrainProtoMessages.ResolveReply) Await.result(akka_reply, Duration.create(4, "seconds"));
}catch(Exception error)
{
return request_error;
}
}
}
);
decode_json = backend_reply.map(
new F.Function<BrainProtoMessages.ResolveReply, ObjectNode>() {
#Override
public ObjectNode apply(BrainProtoMessages.ResolveReply response) throws Throwable {
return new ResolveOutput(response).getJsonReply();
}
}
);
ok_result = decode_json.map(
new F.Function<ObjectNode, Result>() {
#Override
public Result apply(ObjectNode reply) {
return ok(reply);
}
}
);
try {
return ok_result.get(8000);
}catch(Exception error)
{
return internalServerError();
}
}
}

Categories

Resources