Skip to content

FractalX NetScope - Java Access Modifers for the Network Layer

License

Notifications You must be signed in to change notification settings

Project-FractalX/NetScope

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

NetScope by FractalX

NetScope is a Java Spring Boot library that automatically exposes Spring bean methods as network-accessible APIs via both REST and gRPC.

  • Expose any Spring bean method dynamically over REST and gRPC
  • Control access via global or per-method API keys
  • Automatic API documentation with interactive UI
  • Zero manual configuration - just annotate your methods
  • Production-ready with full authentication support

NetScope is perfect for microservice communication, RPC, distributed systems, and dynamic API exposure.

NetScope is developed and maintained by FractalX.


πŸš€ Features

Core Capabilities

  • Dual Protocol Support: Every method works with both REST HTTP and gRPC
  • Two Annotations:
    • @NetworkPublic β†’ Fully open network endpoint
    • @NetworkSecured(key="...") β†’ Protected endpoint requiring authentication
  • Dynamic Discovery: Automatically finds and exposes annotated methods
  • Interactive Documentation:
    • /netscope/docs β†’ JSON API documentation
    • /netscope/docs/ui β†’ Web-based testing interface
  • Flexible Security: Global or per-method API key authentication
  • Streaming Support: gRPC bidirectional streaming for real-time communication

Protocol Features

Feature REST gRPC
Method Invocation βœ… βœ…
Authentication βœ… βœ…
Documentation βœ… βœ…
Streaming ❌ βœ…
Protocol Reflection ❌ βœ…
Binary Efficiency ❌ βœ…

πŸ“¦ Installation

1. Install to Local Maven Repository

# Clone the repository
git clone https://github.com/project-FractalX/netscope-grpc.git
cd netscope-grpc

# Install to local .m2 repository
mvn clean install

2. Add Dependency to Your Project

<dependency>
    <groupId>com.netscope</groupId>
    <artifactId>netscope-grpc</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

3. Ensure Spring Boot Web Starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

βš™οΈ Configuration

application.properties

# REST Server (Spring Boot default)
server.port=8080

# gRPC Server
netscope.grpc.enabled=true
netscope.grpc.port=9090
netscope.grpc.maxInboundMessageSize=4194304

# Security
netscope.security.enabled=true
netscope.security.apiKey=super-secret-global-key

application.yaml

server:
  port: 8080

netscope:
  grpc:
    enabled: true
    port: 9090
    maxInboundMessageSize: 4194304  # 4MB
  security:
    enabled: true
    apiKey: super-secret-global-key

πŸ’» Usage

1. Annotate Your Methods

package com.example.service;

import com.netscope.annotation.NetworkPublic;
import com.netscope.annotation.NetworkSecured;
import org.springframework.stereotype.Service;

@Service
public class CustomerService {

    // Publicly accessible via REST and gRPC
    @NetworkPublic
    public String getCustomers() {
        return "All customers";
    }

    // Requires global API key
    @NetworkSecured
    public int getLoyaltyPoints(String customerId) {
        // Business logic
        return 1250;
    }

    // Requires method-specific API key
    @NetworkSecured(key = "inventory-service-key")
    public int checkStock(String itemId) {
        // Business logic
        return 42;
    }

    // REST-only endpoint
    @NetworkPublic(enableGrpc = false)
    public String getWebOnlyData() {
        return "REST only";
    }

    // gRPC-only endpoint
    @NetworkSecured(key = "grpc-key", enableRest = false)
    public String getGrpcOnlyData() {
        return "gRPC only";
    }
}

🌐 REST API Usage

Public Endpoint

curl http://localhost:8080/netscope/CustomerService/getCustomers

Restricted Endpoint (Global Key)

curl -H "X-API-KEY: super-secret-global-key" \
     http://localhost:8080/netscope/CustomerService/getLoyaltyPoints \
     -d '["CUST123"]'

Restricted Endpoint (Method-Specific Key)

curl -H "X-API-KEY: inventory-service-key" \
     http://localhost:8080/netscope/CustomerService/checkStock \
     -d '["ITEM456"]'

API Documentation

# Get JSON documentation
curl http://localhost:8080/netscope/docs

# Open interactive UI in browser
open http://localhost:8080/netscope/docs/ui

πŸ”Œ gRPC API Usage

Java Client Example

import com.netscope.grpc.proto.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class NetScopeClient {
    public static void main(String[] args) {
        // Create channel
        ManagedChannel channel = ManagedChannelBuilder
            .forAddress("localhost", 9090)
            .usePlaintext()
            .build();

        // Create stub
        NetScopeServiceGrpc.NetScopeServiceBlockingStub stub = 
            NetScopeServiceGrpc.newBlockingStub(channel);

        // Call public method
        GenericRequest publicRequest = GenericRequest.newBuilder()
            .setBeanName("CustomerService")
            .setMethodName("getCustomers")
            .setArgumentsJson("[]")
            .build();

        GenericResponse response = stub.invokeMethod(publicRequest);
        System.out.println("Result: " + response.getResultJson());

        // Call restricted method
        GenericRequest restrictedRequest = GenericRequest.newBuilder()
            .setBeanName("CustomerService")
            .setMethodName("getLoyaltyPoints")
            .setArgumentsJson("[\"CUST123\"]")
            .setApiKey("super-secret-global-key")
            .build();

        GenericResponse response2 = stub.invokeMethod(restrictedRequest);
        System.out.println("Points: " + response2.getResultJson());

        // Get documentation
        DocsRequest docsRequest = DocsRequest.newBuilder().build();
        DocsResponse docs = stub.getDocs(docsRequest);
        
        for (MethodInfo method : docs.getMethodsList()) {
            System.out.println(method.getBeanName() + "." + method.getMethodName());
        }

        channel.shutdown();
    }
}

Python Client Example

import grpc
from netscope_pb2 import GenericRequest, DocsRequest
from netscope_pb2_grpc import NetScopeServiceStub

# Create channel
channel = grpc.insecure_channel('localhost:9090')
stub = NetScopeServiceStub(channel)

# Call public method
request = GenericRequest(
    bean_name="CustomerService",
    method_name="getCustomers",
    arguments_json="[]"
)
response = stub.InvokeMethod(request)
print(f"Result: {response.result_json}")

# Call restricted method
request = GenericRequest(
    bean_name="CustomerService",
    method_name="getLoyaltyPoints",
    arguments_json='["CUST123"]',
    api_key="super-secret-global-key"
)
response = stub.InvokeMethod(request)
print(f"Points: {response.result_json}")

# Get documentation
docs_request = DocsRequest()
docs = stub.GetDocs(docs_request)
for method in docs.methods:
    print(f"{method.bean_name}.{method.method_name}")

Using grpcurl (Command Line)

# List services
grpcurl -plaintext localhost:9090 list

# Describe service
grpcurl -plaintext localhost:9090 describe netscope.NetScopeService

# Call public method
grpcurl -plaintext -d '{
  "bean_name": "CustomerService",
  "method_name": "getCustomers",
  "arguments_json": "[]"
}' localhost:9090 netscope.NetScopeService/InvokeMethod

# Call restricted method
grpcurl -plaintext -d '{
  "bean_name": "CustomerService",
  "method_name": "getLoyaltyPoints",
  "arguments_json": "[\"CUST123\"]",
  "api_key": "super-secret-global-key"
}' localhost:9090 netscope.NetScopeService/InvokeMethod

# Get documentation
grpcurl -plaintext -d '{}' localhost:9090 netscope.NetScopeService/GetDocs

πŸ” Security Patterns

1. Global Security

All restricted methods use the same key:

netscope.security.enabled=true
netscope.security.apiKey=global-master-key

2. Per-Service Keys

Different keys for different services:

@Service
public class PaymentService {
    @NetworkSecured(key = "payment-service-key")
    public Receipt processPayment(Payment payment) {
        // ...
    }
}

@Service
public class UserService {
    @NetworkSecured(key = "user-service-key")
    public User getUser(String id) {
        // ...
    }
}

3. Mixed Security

Public and restricted methods in the same service:

@Service
public class ProductService {
    @NetworkPublic
    public List<Product> getPublicProducts() {
        // Anyone can call
    }

    @NetworkSecured
    public List<Product> getAdminProducts() {
        // Requires authentication
    }
}

πŸ“Š Advanced Features

Streaming (gRPC Only)

// Client-side streaming example
StreamObserver<GenericRequest> requestStream = 
    asyncStub.invokeMethodStream(new StreamObserver<GenericResponse>() {
        @Override
        public void onNext(GenericResponse response) {
            System.out.println("Response: " + response.getResultJson());
        }

        @Override
        public void onError(Throwable t) {
            System.err.println("Error: " + t.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Stream completed");
        }
    });

// Send multiple requests
for (int i = 0; i < 10; i++) {
    GenericRequest request = GenericRequest.newBuilder()
        .setBeanName("DataService")
        .setMethodName("processData")
        .setArgumentsJson("[" + i + "]")
        .build();
    requestStream.onNext(request);
}
requestStream.onCompleted();

Custom URL Mapping

@Configuration
public class CustomMappingConfig {
    @Bean
    public UrlMappingStrategy customUrlMappingStrategy() {
        return (beanClass, method) -> {
            return "/api/v1/" + 
                   beanClass.getSimpleName().toLowerCase() + "/" + 
                   method.getName();
        };
    }
}

🎯 Use Cases

1. Microservice Communication

Replace REST with gRPC for efficient inter-service communication:

@Service
public class OrderService {
    @NetworkSecured(key = "internal-service-key", enableRest = false)
    public Order createOrder(OrderRequest request) {
        // Internal service communication via gRPC only
    }
}

2. External API + Internal RPC

Public REST API for external clients, gRPC for internal:

@Service
public class UserService {
    @NetworkPublic(enableGrpc = false)  // REST only for external
    public UserProfile getPublicProfile(String userId) {
        // Public REST API
    }

    @NetworkSecured(key = "internal", enableRest = false)  // gRPC only
    public UserDetails getInternalDetails(String userId) {
        // Internal service communication
    }
}

3. Dynamic Service Registry

Automatically discover all available services:

@Service
public class ServiceDiscovery {
    @Autowired
    private NetScopeScanner scanner;

    public List<String> listAllServices() {
        return scanner.scan().stream()
            .map(m -> m.getBeanName() + "." + m.getMethodName())
            .collect(Collectors.toList());
    }
}

πŸ› οΈ Development & Testing

Running Tests

mvn test

Building the Library

mvn clean package

Installing Locally

mvn clean install

Protocol Buffer Compilation

The proto files are automatically compiled during the Maven build. Generated files are in target/generated-sources/protobuf/.


πŸ“‹ System Requirements

  • Java 21+
  • Spring Boot 3.2+
  • Maven 3.6+ (for building)
  • gRPC 1.61+ (included as dependency)

πŸ”§ Troubleshooting

gRPC Server Not Starting

Check if the port is available:

lsof -i :9090

Enable gRPC explicitly:

netscope.grpc.enabled=true

Authentication Failures

Verify your API key configuration:

curl -v -H "X-API-KEY: your-key" http://localhost:8080/netscope/docs

Check logs for authentication details.

Method Not Found

Ensure your service is a Spring bean (@Service, @Component, etc.) and the method has the correct annotation.


πŸ“š API Reference

Annotations

@NetworkPublic

@NetworkPublic(
    path = "",                  // Custom REST path (optional)
    method = RequestMethod.GET, // HTTP method (default: GET)
    enableRest = true,          // Enable REST endpoint (default: true)
    enableGrpc = true           // Enable gRPC endpoint (default: true)
)

@NetworkSecured

@NetworkSecured(
    key = "",                   // Per-method API key (optional, uses global if empty)
    method = RequestMethod.GET, // HTTP method (default: GET)
    path = "",                  // Custom REST path (optional)
    enableRest = true,          // Enable REST endpoint (default: true)
    enableGrpc = true           // Enable gRPC endpoint (default: true)
)

gRPC Service

service NetScopeService {
    rpc InvokeMethod (GenericRequest) returns (GenericResponse);
    rpc GetDocs (DocsRequest) returns (DocsResponse);
    rpc InvokeMethodStream (stream GenericRequest) returns (stream GenericResponse);
}

🀝 Contributing

External contributions are NOT welcomed yet! We're working on establishing our contribution guidelines.


πŸ‘₯ Authors


πŸ“„ License

NetScope is licensed under the Apache License 2.0. See the LICENSE file for details.


🌟 Why NetScope?

  • Zero Boilerplate: No manual controller or service definitions
  • Polyglot: Works with any gRPC-supported language
  • Production Ready: Full authentication and security support
  • Developer Friendly: Interactive documentation UI
  • Flexible: Choose REST, gRPC, or both for each method
  • Type Safe: Automatic parameter marshaling and type conversion
  • Discoverable: Built-in service discovery and documentation

πŸ”— Links


NetScope - Making every Java method a network API πŸš€

About

FractalX NetScope - Java Access Modifers for the Network Layer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published