R for Maven

Maven Central
License
Java

Type-safe hierarchical resource access for Java Maven projects – inspired by Android’s R.java!

Generate a type-safe, hierarchical R.java class that mirrors your resource directory structure. Access files and folders with intuitive syntax like R.config.database.readContent() while enjoying full IDE autocompletion and compile-time validation.

✨ Features

  • πŸ“ Hierarchical Structure – Mirrors your resources directory tree
  • πŸ—οΈ Build Integration – Generates during Maven compilation
  • πŸ”€ Smart Naming – Converts file/folder names to camelCase Java identifiers
  • πŸ“– Rich File API – Built-in methods for reading, streaming, and path manipulation
  • πŸ“‚ Folder Methods – Access folder metadata with myFolder._self .getName()getPath()
  • ⚑ Fast Generation – Lightweight and efficient

πŸ“¦ Installation

Add the plugin to your pom.xml:

<dependencies>
    <!-- Required: the R class use various dependancy such as org.jetbrains.annotations -->
    <dependency>
        <groupId>com.enosistudio</groupId>
        <artifactId>r-for-maven</artifactId>
        <version>1.0.2</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>com.enosistudio</groupId>
            <artifactId>r-for-maven</artifactId>
            <version>1.0.2</version>
            <configuration>
                <keepInProjectFiles>true</keepInProjectFiles> <!-- Optional: keep generated files in project -->
                <resourcesDir>${project.basedir}/src/main/resources</resourcesDir> <!-- Optional: specify resources directory -->
                <outputSrcDirectory>${project.basedir}/src/main/java</outputSrcDirectory> <!-- Optional: specify output source directory -->
                <outputTargetDirectory>${project.build.directory}/generated-sources</outputTargetDirectory> <!-- Optional: specify output target directory -->
                <packageName>com.enosistudio.generated</packageName> <!-- Optional: specify package name -->
            </configuration>
            <executions>
                <execution>
                    <phase>generate-sources</phase> <!-- Optional: Can help intellij to not bug when creating the source folder, when using <keepInProjectFiles>false</keepInProjectFiles> -->
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

πŸƒβ€β™‚οΈ Usage

Before (❌ Error-prone)

// Hardcoded strings everywhere!
InputStream config = getClass().getResourceAsStream("/config/database.properties");
InputStream logo = getClass().getResourceAsStream("/images/icons/logo.png");

// Typos cause runtime errors πŸ’₯
String content = Files.readString(Paths.get("config/databse.properties")); // Whoops!

After (βœ… Type-safe & Intuitive)

import com.enosistudio.generated.R;

// Hierarchical access with autocompletion!
String content = R.config.databaseProperties.readContent();
InputStream logo = R.images.icons.logoPng.openStream();
URL resource = R.templates.emailHtml.getURL();

// Folder information
String folderName = R.config._self.getName();     // "config"
String folderPath = R.config._self.getPath();     // "config"

// Compile-time safety πŸ›‘οΈ
R.config.databseProperties.readContent(); // Won't compile - no typos possible!

πŸ“‚ Generated Structure

Your Resources:

src/main/resources/
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ database.properties
β”‚   └── app-settings.yml
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ email.html
β”‚   └── reports/
β”‚       └── invoice.pdf
└── logo.png

Generated R.java:

package com.enosistudio.generated;

public final class R {
    public static final RFile logoPng = new RFile("logo.png");
    
    public static final class config extends RFolder {
        public static final RFolder _self = new config();
        private config() { super("config", "config"); }
        
        public static final RFile databaseProperties = new RFile("config/database.properties");
        public static final RFile appSettingsYml = new RFile("config/app-settings.yml");
    }
    
    public static final class templates extends RFolder {
        public static final RFolder _self = new templates();
        private templates() { super("templates", "templates"); }
        
        public static final RFile emailHtml = new RFile("templates/email.html");
        
        public static final class reports extends RFolder {
            public static final RFolder _self = new reports();
            private reports() { super("reports", "templates/reports"); }
            
            public static final RFile invoicePdf = new RFile("templates/reports/invoice.pdf");
        }
    }
    
    // Built-in utility classes for files and folders
    public static class RFolder { /* folder methods */ }
    public static final class RFile { /* rich file API */ }
}

βš™οΈ Configuration

ParameterDefaultDescription
keepInProjectFilestrueKeep generated files in src/main/java
resourcesDirsrc/main/resourcesResources directory to scan
packageNamecom.enosistudio.generatedPackage for generated R.java
outputSrcDirectorysrc/main/javaOutput when keepInProjectFiles=true
outputTargetDirectorytarget/generated-sourcesOutput when keepInProjectFiles=false

πŸ”§ Requirements

  • β˜• Java 11+
  • πŸ”¨ Maven 3.6+

⭐ Star this repo if it helps!