SkillAgentSearch skills...

Nano

tiny java tool - back to basics!

Install / Use

/learn @NanoNative/Nano
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🧬 Project Nano

[![Issues][issues_shield]][issues_link] [![Commit][commit_shield]][commit_link] [![License][license_shield]][license_link] [![Central][central_shield]][central_link] [![Tag][tag_shield]][tag_link] [![Javadoc][javadoc_shield]][javadoc_link] [![Size][size_shield]][size_shield] ![Label][label_shield] ![Label][java_version]

Introduction | Core Concept | Mechanics | Components | Getting Started | Build Nano | Benefits

🖼️ Introduction

Back to basics and forget about frameworks!

Nano is a lightweight approach which makes it easier for developer to write microservices in functional, fluent, chaining, plain, modern java with a nano footprint. It breaks away from traditional OOP patterns. Instead of creating complex object hierarchies with Controllers, Services, and Repositories, Nano uses static event listeners that react to events in a functional, stateless manner.

Key Philosophy:

  • Static Methods, Not Objects: Business logic lives in static methods, not in service objects
  • Event-Driven Communication: Everything communicates through events, not direct method calls
  • Universal Services: Services are generic connectors for external systems (databases, HTTP, queues) - no business logic
  • TypeMap Everywhere: Built-in type conversion and data transformation using TypeMap
  • Global Error Handling: Even errors are events that can be subscribed to and handled globally

Nano is designed to be fully compilable with GraalVM to create native executables and utilizes non-blocking virtual threads from Project Loom for maximum performance.

📐 Core Concept

Think Events, Not Objects!

Nano revolutionizes microservice development by eliminating the need for complex object hierarchies. Instead of creating Controllers, Services, and Repositories, you simply listen to events and react with static methods.

How It Works:

  1. Events Flow Through Everything: HTTP requests, database operations, errors - all are events
  2. Static Listeners React: Your business logic lives in static methods that subscribe to events
  3. Services Are Universal Connectors: Services handle external integrations (HTTP, databases, queues) - no business logic
  4. TypeMap Handles Data: Automatic type conversion for JSON, XML, and any data format
  5. Global Error Handling: Subscribe to error events for centralized error management

Example - Traditional vs Nano:

// ❌ Traditional Spring Boot
@RestController
public class UserController {
    @Autowired private UserService userService;
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody UserDto dto) {
        return ResponseEntity.ok(userService.createUser(dto));
    }
}

// ✅ Nano - Static Event Handling
public class UserController {
    public static void handleCreateUser(Event<HttpObject, HttpObject> event) {
        event.payloadOpt()
            .filter(HttpObject::isMethodPost)
            .filter(req -> req.pathMatch("/users"))
            .ifPresent(req -> {
                // Business logic here - no objects needed!
                event.context().sendEvent(EVENT_CREATE_USER, req.bodyAsJson().asMap());
                req.createResponse().statusCode(200).respond(event);
            });
    }
}

Read more...

📚 Components

All you need to know are few classes: Context, Events, Schedulers, Services

flowchart LR
    nano(((Nano))) --> context[Context]
    context --> ch[Channels]
    nano --> services[Services]
    context --> schedulers[Schedulers]
    ch -->|sendEvent| listeners[Listeners]
    services -->|ack/reply| responses[(Responses)]
    listeners -->|ack/reply| responses[(Responses)]
    
    style nano fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style context fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style ch fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style listeners fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style responses fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style services fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%
    style schedulers fill:#90CAF9,stroke:#1565C0,stroke-width:1px,color:#1A237E,rx:2%,ry:2%

⚙️ Mechanics

The Nano Way: Static, Event-Driven, and Stateless

Nano's architecture is fundamentally different from traditional frameworks:

🏗️ Architecture Principles:

  • Static Methods for Business Logic: No need for service objects - just static methods that react to events
  • Services as Universal Connectors: Services handle external integrations only (databases, HTTP, queues) - no business logic
  • Event-Driven Communication: Everything flows through events - HTTP requests, database operations, errors
  • TypeMap for Data Handling: Automatic type conversion and transformation for JSON, XML, and any data format
  • Global Error Handling: Subscribe to error events for centralized error management
  • Built-in Logging: Context automatically provides logging - no setup required

🔄 How It All Connects:

  1. HTTP RequestEventStatic ListenerBusiness Logic
  2. Database OperationEventDatabase ServiceResponse Event
  3. Error OccursError EventGlobal Error HandlerError Response

📚 Getting Started

Maven example

<dependency>
    <groupId>org.nanonative</groupId>
    <artifactId>nano</artifactId>
    <version>2025.1.0</version>
</dependency>

Gradle example

dependencies {
    implementation 'org.nanonative:nano:2025.1.0'
}

Quick Start

New to Nano? Start with our Quick Start Guide for a complete walkthrough.

Want to see examples? Check out our Examples & Common Solutions with real-world patterns.

Building a web API? Check out our HTTP Service Guide with real-world examples.

Need architecture guidance? See our Core Concepts for best practices.

Looking for documentation? Check out our comprehensive guides in the docs directory.

Simple Example

Here's a basic HTTP server with Nano showing the event-driven approach:

public static void main(final String[] args) {
    // Start Nano with HttpServer
    final Nano app = new Nano(args, new HttpServer());

    // Static method handles GET /hello - no @Controller needed!
    app.subscribeEvent(EVENT_HTTP_REQUEST, MyController::handleHello);

    // Global error handling - even errors are events!
    app.subscribeError(EVENT_HTTP_REQUEST, MyController::handleError);
}

public class MyController {
    // Static method for business logic - no objects, no state!
    public static void handleHello(Event<HttpObject, HttpObject> event) {
        event.payloadOpt()
            .filter(HttpObject::isMethodGet)
            .filter(request -> request.pathMatch("/hello"))
            .ifPresent(request -> request.createResponse()
                .body(Map.of("Hello", System.getProperty("user.name")))
                .respond(event));
    }
    
    // Global error handling - subscribe to error events!
    public static void handleError(Event<?, ?> event) {
        event.payloadAck()
            .createResponse()
            .body("Internal Server Error [" + event.error().getMessage() + "]")
            .statusCode(500)
            .respond(event);
    }
}

Real-World Examples

🔨 Build Nano

add the native-image profile to your pom.xml and run mvn package -Pnative-image


<profiles>
    <!-- NATIVE COMPILATION -->
    <plugin>
        <groupId>org.graalvm.nativeimage</groupId>
        <artifactId>native-image-maven-plugin</artifactId>
        <version>21.2.0</version>
        <configuration>
            <imageName>ExampleApp</imageName>
            <mainClass>de.yuna.berlin.nativeapp.helper.ExampleApp</mainClass>
            <buildArgs>
                <!-- Reduces the image size - Ensures the native image doesn't include the JVM as a fallback option -->
                <buildArg>--no-fallback</buildArg>
                <!-- Disables the use of the GraalVM compilation server -->
                <buildArg>--no-server</buildArg>
                <!-- Improve startup time - Initialize classes at build time rather than at runtime -->
                <buildArg>--initialize-at-build-time</buildArg>
                <!-- Include all files under /resources -->
                <buildArg>-H:IncludeResources=resources/config/.*</buildArg>
            </buildArgs>
        </configuration>
        <executions>
       
View on GitHub
GitHub Stars104
CategoryDevelopment
Updated29d ago
Forks4

Languages

Java

Security Score

95/100

Audited on Feb 27, 2026

No findings