Local gRPC Server
This playbook provides instructions for running the ArchitecturalPlanServer locally for development and testing.
Prerequisites
- Java 23 (as specified in pom.xml)
- Maven
- Google Cloud authentication (if using GCP services)
- grpcurl (for testing)
Environment Setup
Load the development environment variables:
source env/dev/setvars.sh
Starting the Server
Method 1: Using Maven Exec Plugin (Recommended for Development)
Fastest method for development - no need to build JAR each time:
mvn exec:java -Dexec.mainClass="org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer"
With custom port:
mvn exec:java -Dexec.mainClass="org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer" -Dexec.args="8081"
Method 2: Build and Run JAR (Recommended for Production-like Testing)
Build the executable JAR with dependencies:
mvn clean package -DskipTests
Run the JAR file:
java -jar target/construction-code-expert-1.0-SNAPSHOT-jar-with-dependencies.jar
With custom port:
java -jar target/construction-code-expert-1.0-SNAPSHOT-jar-with-dependencies.jar 8081
Method 3: Using Java Classpath with Explicit Main Class Override
Get the latest built JAR file:
LATEST_JAR_FILE=$(ls target/construction-code-expert-*-jar-with-dependencies.jar | sort -V | tail -n 1)
Run with explicit main class:
java -cp "$LATEST_JAR_FILE" org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer
With custom port:
java -cp "$LATEST_JAR_FILE" org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer 8081
Overriding Filesystem Handler for Local Development
By default, the services use GcsFileSystemHandler which requires Google Cloud Storage. For local development, you can override this to use LocalFileSystemHandler instead.
Option 1: Environment Variable Override (Recommended)
Add this to your env/dev/setvars.sh or set it before starting the server:
export CODEPROOF_USE_LOCAL_FILESYSTEM=true
Then modify the getDefaultFilesystemHandler() method in each service to check for this environment variable:
private FileSystemHandler getDefaultFilesystemHandler() {
if(overrideFileSystemHandler != null) {
return overrideFileSystemHandler;
}
// Check for local filesystem override
String useLocalFs = Utils.getenv("CODEPROOF_USE_LOCAL_FILESYSTEM");
if ("true".equalsIgnoreCase(useLocalFs)) {
return new LocalFileSystemHandler();
}
return new GcsFileSystemHandler(Utils.getenv("GCP_GCS_BUCKET_NAME"));
}
Option 2: Programmatic Override
Create a custom server startup class that sets the override:
public class LocalArchitecturalPlanServer {
public static void main(String[] args) throws IOException, InterruptedException {
final ArchitecturalPlanServer server = new ArchitecturalPlanServer();
// Create service instances and set local filesystem handler
ArchitecturalPlanServiceImpl architecturalPlanService = new ArchitecturalPlanServiceImpl();
architecturalPlanService.setOverrideFileSystemHandler(new LocalFileSystemHandler());
ArchitecturalPlanReviewServiceImpl reviewService = new ArchitecturalPlanReviewServiceImpl();
reviewService.setOverrideFileSystemHandler(new LocalFileSystemHandler());
ComplianceCodeSearchServiceImpl searchService = new ComplianceCodeSearchServiceImpl();
searchService.setOverrideFileSystemHandler(new LocalFileSystemHandler());
// Start server with custom services
server.start(8080, architecturalPlanService, reviewService, searchService);
server.blockUntilShutdown();
}
}
Option 3: Using a Local Development Script
Create a script that sets up the local filesystem handler:
#!/bin/bash
# cli/start-local-server.sh
# Load environment variables
source env/dev/setvars.sh
# Set local filesystem flag
export CODEPROOF_USE_LOCAL_FILESYSTEM=true
# Start the server
mvn exec:java -Dexec.mainClass="org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer"
Usage:
./cli/start-local-server.sh
Local Data Structure
When using LocalFileSystemHandler, ensure your local directory structure matches what the services expect:
your-project-root/
├── database/
│ └── icc-irc/
│ └── index.json
├── inputs/
│ └── architectural-plans/
│ └── R2024.0091-2024-10-14/
│ ├── page-1/
│ │ ├── page.pdf
│ │ └── page.md
│ └── page-2/
│ ├── page.pdf
│ └── page.md
└── api/
└── icc/
└── content.chapters.3757.json
Server Configuration
- Default port: 8080
- Services provided:
ArchitecturalPlanServiceImplArchitecturalPlanReviewServiceImplComplianceCodeSearchServiceImplAccessControlListServiceImpl
Testing the Server
Install grpcurl (if not already installed)
# macOS
brew install grpcurl
# Ubuntu/Debian
sudo apt-get install grpcurl
# Or download from: https://github.com/fullstorydev/grpcurl/releases
Basic Testing
List available services:
grpcurl -plaintext localhost:8080 list
Describe a specific service:
grpcurl -plaintext localhost:8080 describe org.codetricks.construction.code.assistant.service.ArchitecturalPlanService
Alternative: List services with explicit proto paths (if reflection doesn't work):
grpcurl -plaintext \
-import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
localhost:8080 \
list
Example API Calls
Get Architectural Plan:
grpcurl -plaintext \
-import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14"}' \
localhost:8080 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlan
Get Architectural Plan Page PDF (with increased message size):
grpcurl -plaintext \
-import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14", "page_number": 1}' \
-max-msg-sz $((10 * 1024 * 1024)) \
localhost:8080 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlanPagePdf
Search ICC Code:
grpcurl -plaintext \
-import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
-d '{"icc_book_id": "2217", "query": "Cooling towers located on a roof of a building shall be constructed of non-combustible materials when the base area of the cooling tower is greater than how many square feet?", "max_results": 3}' \
localhost:8080 \
org.codetricks.construction.code.assistant.service.ComplianceCodeSearchService/GetIccCodeSearchResults
Troubleshooting
Port Already in Use
If you get a "port already in use" error, either:
- Kill the existing process using the port
- Use a different port number as shown in the examples above
Memory Issues
The server may require significant memory for processing large PDF files. If you encounter memory issues:
- Increase JVM heap size:
java -Xmx4g -jar target/construction-code-expert-1.0-SNAPSHOT-jar-with-dependencies.jar - Or use Maven with increased memory:
MAVEN_OPTS="-Xmx4g" mvn exec:java -Dexec.mainClass="org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer"
Authentication Issues
If you encounter Google Cloud authentication issues:
- Ensure you have proper GCP credentials set up
- Check that the environment variables in
env/dev/setvars.share correctly configured - Verify your GCP project has the necessary APIs enabled
Filesystem Handler Issues
If you encounter filesystem-related errors:
- Ensure your local data structure matches the expected layout
- Check that the
CODEPROOF_USE_LOCAL_FILESYSTEMenvironment variable is set correctly - Verify that the local files and directories exist and are readable
Development Workflow
- For active development: Use Method 1 (Maven exec plugin)
- For testing production-like behavior: Use Method 2 (JAR execution)
- For running different main classes: Use Method 3 (classpath override)
- For local development without GCS: Use the filesystem override options
Related Files
src/main/java/org/codetricks/construction/code/assistant/service/ArchitecturalPlanServer.java- Main server classsrc/main/java/org/codetricks/construction/code/assistant/service/ArchitecturalPlanServiceImpl.java- Service implementation with filesystem handlersrc/main/java/org/codetricks/construction/code/assistant/data/rag/corpus/LocalFileSystemHandler.java- Local filesystem implementationenv/dev/setvars.sh- Development environment variablespom.xml- Maven configuration with main class specificationsrc/main/assembly/assembly.xml- JAR assembly configurationcli/codeproof.sh- Example of classpath override approach
Running Local HTTP REST Service with ESPv2
For local development with HTTP REST transcoding (similar to Cloud Run ESPv2), you can run ESPv2 locally with Docker.
Prerequisites
- Docker installed and running
protoc(Protocol Buffers compiler) installed- gRPC server running on port 8080
Start Local ESPv2
Step 1: Start the gRPC server first
./cli/start-local-server.sh
Step 2: Start ESPv2 proxy (in a new terminal)
./cli/start-local-espv2.sh
The ESPv2 script will:
- Check if gRPC server is running on port 8080
- Generate the API descriptor from your proto files
- Start ESPv2 Docker container on port 8081
- Provide HTTP REST API endpoints that proxy to your gRPC server
Local Environment Configuration
The local ESPv2 setup uses the environment structure at env/local/gcp/cloud-run/endpoints/:
api_config.yaml- ESPv2 service configurationsetvars.sh- Local environment variablesvars.yaml- Environment variables for ESPv2
Testing HTTP REST API
Once both services are running, you can test the HTTP REST endpoints:
# List architectural plans
curl http://localhost:8081/v1/architectural-plans
# Get specific architectural plan
curl http://localhost:8081/v1/architectural-plans/R2024.0091-2024-10-14
# Search ICC codes
curl -X POST http://localhost:8081/v1/icc-books/2217/search \
-H "Content-Type: application/json" \
-d '{"query": "Cooling towers", "max_results": 3}'
Port Configuration
- gRPC Server:
localhost:8080(started withstart-local-server.sh) - HTTP REST API:
localhost:8081(ESPv2 proxy)
Stopping Services
Stop ESPv2 only:
docker stop local-espv2
docker rm local-espv2
Stop gRPC server:
pkill -f "ArchitecturalPlanServer"
Or press Ctrl+C in the respective terminal windows.