0

I am currently trying to send a request to a nodejs server from a java client that I created but I am getting the error that is showing above. I've been doing some research on it but can seem to figure out why it is happening. The server I created in nodejs:

var grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader')
const packageDefinition = protoLoader.loadSync('AirConditioningDevice.proto')

var AirConditioningDeviceproto = grpc.loadPackageDefinition(packageDefinition);

var AirConditioningDevice = [{
    device_id: 1,
    name: 'Device1',
    location: 'room1',
    status: 'On',
    new_tempature: 11
}];

var server = new grpc.Server();
server.addService(AirConditioningDeviceproto.AirConditioningDevice.Airconditioning_service.service,{
    currentDetails: function(call, callback){
        console.log(call.request.device_id);
        for(var i =0; i <AirConditioningDevice.length; i++){
            console.log(call.request.device_id);
             if(AirConditioningDevice[i].device_id == call.request.device_id){
                console.log(call.request.device_id);
                 return callback(null, AirConditioningDevice [i]);
             }
             console.log(call.request.device_id);
        }
        console.log(call.request.device_id);
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });
    },
    setTemp: function(call, callback){
        for(var i =0; i <AirConditioningDevice.length; i++){
             if(AirConditioningDevice[i].device_id == call.request.device_id){

                 AirConditioningDevice[i].new_tempature == call.request.new_tempature;
                 return callback(null, AirConditioningDevice[i]);
             }
        }
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });

    },
    setOff: function(call, callback){
        for(var i =0; i <AirConditioningDevice.length; i++){
             if(AirConditioningDevice[i].device_id == call.request.device_id && AirConditioningDevice[i].status == 'on'){
                 AirConditioningDevice[i].status == 'off';
                 return callback(null, AirConditioningDevice[i]);
             }else{
                 AirConditioningDevice[i].status == 'on';
                 return callback(null, AirConditioningDevice[i]);
             }
        }
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });
    }
});

server.bind('localhost:3000', grpc.ServerCredentials.createInsecure());
server.start();

This is the client that I have created in java:

package com.air.grpc;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import com.air.grpc.Airconditioning_serviceGrpc;

import com.air.grpc.GrpcClient;
import com.air.grpc.deviceIDRequest;
import com.air.grpc.ACResponse;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

public class GrpcClient {
    private static final Logger logger = Logger.getLogger(GrpcClient.class.getName());
    private final ManagedChannel channel;
    private final Airconditioning_serviceGrpc.Airconditioning_serviceBlockingStub blockingStub;
     private final Airconditioning_serviceGrpc.Airconditioning_serviceStub asyncStub;

     public GrpcClient(String host, int port) {
            this(ManagedChannelBuilder.forAddress(host, port)
                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                // needing certificates.
                .usePlaintext()
                .build());
          }
     GrpcClient(ManagedChannel channel) {
            this.channel = channel;
            blockingStub = Airconditioning_serviceGrpc.newBlockingStub(channel);
            asyncStub = Airconditioning_serviceGrpc.newStub(channel);
          }
     public void shutdown() throws InterruptedException {
            channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
          }

     public void currentDetails(int id) {
         logger.info("Will try to get device " + id + " ...");
         deviceIDRequest deviceid = deviceIDRequest.newBuilder().setDeviceId(id).build();
         ACResponse response;
         try {
             response =blockingStub.currentDetails(deviceid);

         }catch(StatusRuntimeException e) {
             logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
              return;
         }
          logger.info("Device: " + response.getAirConditioning ());

     }
     public static void main(String[] args) throws Exception {
         GrpcClient client = new GrpcClient("localhost", 3000);
         try {
             client.currentDetails(1);
         }finally {
            client.shutdown();
        }



          }




}

Right now the only one that I have tested cause its the most basic one is currentdetails. As you can see I have created an AirConditioningDevice object. I am trying to get the details of it by typing in 1 to a textbox which is the id but like i said when i send it i get the error in the title. This is the proto file that I have created:

syntax = "proto3";


package AirConditioningDevice;

option java_package = "AircondioningDevice.proto.ac";


service Airconditioning_service{
rpc currentDetails(deviceIDRequest) returns (ACResponse) {};
rpc setTemp( TempRequest ) returns (ACResponse) {};
rpc setOff(deviceIDRequest) returns (ACResponse) {};



}

message AirConditioning{
int32 device_id =1;
string name = 2;
string location = 3;
string status = 4;
int32 new_tempature = 5;
}

message deviceIDRequest{
int32 device_id =1;

}

message TempRequest {
    int32 device_id = 1;
    int32 new_temp = 2;
}

message ACResponse {
    AirConditioning airConditioning = 1;
}

lastly this is everything I get back in the console:

Apr 02, 2020 4:23:29 PM AircondioningDevice.proto.ac.AirConClient currentDetails
INFO: Will try to get device 1 ...
Apr 02, 2020 4:23:30 PM AircondioningDevice.proto.ac.AirConClient currentDetails
WARNING: RPC failed: Status{code=NOT_FOUND, description=Not found, cause=null}

I dont know whether I am completely off or if the error is small. Any suggestions? One other thing is I the same proto file in the java client and the node server I dont know if that matters. One last this is I also get this when i run my server: DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead I dont know if that has anything to do with it.

  • It would make it a lot easier to figure out what's going wrong if you could show some minimal code that reproduces the problem you are seeing. In particular, create a client that does nothing but perform the specific requests that result in this error, without all of the GUI code or whatever you have there. – murgatroid99 Apr 02 '20 at 17:44
  • okay ill edit my question now – Gavin Smith Apr 02 '20 at 18:14
  • sorry it took so long to edit i was having trouble with my dependencies but anyway I have added a simple simple client know with a hard coded ID request. I'm still getting the same error though. – Gavin Smith Apr 02 '20 at 20:28
  • I'm not sure if this is contributing to the problem, but the lack of braces around the contents of the for loop and if statement in the service handler make it difficult to follow. – murgatroid99 Apr 02 '20 at 21:49
  • Sorry ive cleaned it up so hopefully its easier to read now but sadly that was not the problem. – Gavin Smith Apr 02 '20 at 22:15

1 Answers1

0

In your .proto file, you declare deviceIDRequest with a field device_id, but you are checking call.request.id in the currentDetails handler. If you look at call.request.id directly, it's probably undefined.

You also aren't getting to this bit yet, but the success callback is using the books array instead of the AirConditioningDevice array.

murgatroid99
  • 19,007
  • 10
  • 60
  • 95
  • They would have most definitely caused an error in the next stage so thank you but I made the changes you suggested and I am still getting the same error :( – Gavin Smith Apr 02 '20 at 22:33
  • Has it got anything to do with me having a proto file in the java client and a proto file in the node server?? – Gavin Smith Apr 02 '20 at 22:35
  • I assume you mean that you changed the handler on the server to check `call.request.device_id`. What is the value of that in the handler function? – murgatroid99 Apr 02 '20 at 22:38
  • I changed everything that said id to device_id ill edit my question to show you :) – Gavin Smith Apr 02 '20 at 22:43
  • What is the value of `call.request.device_id` in the handler function? – murgatroid99 Apr 02 '20 at 22:52
  • I have it set to 1. – Gavin Smith Apr 02 '20 at 22:54
  • OK, add a couple of `console.log` calls in the handler function. Log `call.request.device_id`, the `device_id` of each member of `AirConditioningDevice` in the loop, and add log lines in the if statement before calling the success callback and right before calling the failure callback.The check the output to see what is happening. – murgatroid99 Apr 02 '20 at 23:03
  • I put in 4 console logs in everyplace that you said and when i ran the client i got 4 outputs in the server saying undefined. I ran the client again and I got another 4 saying the same thing. I dont know if that helps? – Gavin Smith Apr 02 '20 at 23:14
  • OK, that shouldn't be possible. Just edit those log calls into your question and I'll take a look. – murgatroid99 Apr 02 '20 at 23:22
  • First, `call.request.device_id` being `undefined` is definitely the problem. Add a `console.log(call.request)` to the beginning to see what's in there. Also, you should log different things in those different lines so that you know which output corresponds to which log line. There's no point in logging `call.request.device_id` multiple times, because you never change it. You should log `AirConditioningDevice[i].device_id` in the first log line in the loop, and other things in the other log lines. – murgatroid99 Apr 02 '20 at 23:34
  • when I do `console.log(call.request)` at the start of the function it says `{ deviceId: 1 }` which I think is a good thing as i know know that it is being sent. when I do `console.log(AirConditioningDevice[i].device_id)` in the loop the output is undefined and I also added `console.log(call.request.device_id); under that and it also says undefined. – Gavin Smith Apr 02 '20 at 23:44
  • I changed it in the server to deviceId and all the responses were 1 yay. Thanks so much. the only thing is the response was empty for some reason. – Gavin Smith Apr 03 '20 at 00:01
  • Oh, I see the problem now. See the documentation for the [proto-loader package](https://www.npmjs.com/package/@grpc/proto-loader) about the `keepCase` option. Also, maybe try removing the space between `AirConditioningDevice` and `[i]` where you are calling the success callback. – murgatroid99 Apr 03 '20 at 00:19
  • I've added the keep case option thank you. i also moved the [i] beside the AirConditioningDevice but unfortunately Its still empty its probably something small. – Gavin Smith Apr 03 '20 at 00:39
  • Oh, now I see the problem. You declared `ACResponse` as a message with a single field `airConditioning` that contains an `AirConditioning` message. You have to return an object with that structure. – murgatroid99 Apr 03 '20 at 00:59
  • hmm this might be a stupid question but i don't really no what you mean could you explain please? – Gavin Smith Apr 03 '20 at 01:07
  • do you mean use: repeated ? – Gavin Smith Apr 03 '20 at 01:09
  • What I mean is that the members of the `AirConditioningDevice` array have a structure that matches the `AirConditioning` message. The response type of `currentDetails` (really, all of your methods) is not the `AirConditioning` message. It is `ACResponse`, a message with a field `airConditioning` that contains an `AirConditioning`. So, the object you pass to the callback should be an object with a field `airConditioning` that contains an object with the same structure as the `AirConditioning` message. In other words, you want `callback(nulll, { airConditioning: AirConditioningDevice[i] })`. – murgatroid99 Apr 03 '20 at 01:14
  • yes that worked. thanks so much for all your help i'm sure many people would have left by now lol. I marked this answer as complete. – Gavin Smith Apr 03 '20 at 01:20