Search code examples
javastreamsets

Issues in accessing the instances of one class within other class


I am trying to access the instances with in a method of one class within another class and tried modifying them. But it is throwing me the error as "Cannot refer to the non-final local variable nextSourceOffset defined in an enclosing scope.And it is giving me a fix to modify the variable to final".But if I change it to final, I cannot increment them.

I am using the following code:

public String produce(String lastSourceOffset, final int maxBatchSize, BatchMaker batchMaker)
            throws StageException {
        long nextSourceOffset = 0;
        if (lastSourceOffset != null) {
            nextSourceOffset = Long.parseLong(lastSourceOffset);
        }
        final RtmClient client = new RtmClientBuilder(getEndPoint(), getAppKey()).setListener(new RtmClientAdapter() {
            @Override
            public void onEnterConnected(RtmClient client) {

            }
        }).build();
        SubscriptionAdapter listener = new SubscriptionAdapter() {

            @Override
            public void onSubscriptionData(SubscriptionData data) {
                int numRecords = 0;
                for (AnyJson json : data.getMessages()) {
                    jsonString = json.toString();
                    Record record = getContext().createRecord("some-id::" + nextSourceOffset);
                    Map<String, Field> map = new HashMap<>();
                    map.put("fieldName", Field.create(jsonString));
                    record.set(Field.create(map));
                    batchMaker.addRecord(record);
                    ++nextSourceOffset;
                    ++numRecords;

                }
            }

        };

It is throwing the error at:

Record record = getContext().createRecord("some-id::" + nextSourceOffset);//error 
                    Map<String, Field> map = new HashMap<>();
                    map.put("fieldName", Field.create(jsonString));
                    record.set(Field.create(map));
                    batchMaker.addRecord(record);//error
                    ++nextSourceOffset;//error
                    ++numRecords;//error

Solution

  • Your inner class can not access a non-final variable from the outside scope. It can not change the value of the variable either.

    The cleanest solution would probably be to encapsulate all this information within a new class and have it stored as attributes.

    The quick-and-dirty solution would be to make your local long variables into single element arrays of type long. The variable itself would be final as it would always reference the same array, but the content of the array could still be changed.

    Example:

     public String produce(String lastSourceOffset, final int maxBatchSize, BatchMaker batchMaker)
            throws StageException {
        long[] nextSourceOffset = {0};
        if (lastSourceOffset != null) {
            nextSourceOffset[0] = Long.parseLong(lastSourceOffset);
        }
        final RtmClient client = new RtmClientBuilder(getEndPoint(), getAppKey()).setListener(new RtmClientAdapter() {
            @Override
            public void onEnterConnected(RtmClient client) {
    
            }
        }).build();
        SubscriptionAdapter listener = new SubscriptionAdapter() {
    
            @Override
            public void onSubscriptionData(SubscriptionData data) {
                int numRecords = 0;
                for (AnyJson json : data.getMessages()) {
                    jsonString = json.toString();
                    Record record = getContext().createRecord("some-id::" + nextSourceOffset[0]);
                    Map<String, Field> map = new HashMap<>();
                    map.put("fieldName", Field.create(jsonString));
                    record.set(Field.create(map));
                    batchMaker.addRecord(record);
                    ++nextSourceOffset[0];
                    ++numRecords;
    
                }
            }
    
        };