# JNBridge LoggerDemo — Reference Project

This is a working reference project that demonstrates **.NET Framework (C#) calling Java code via JNBridge Pro v12.0** using shared-memory transport. Use it as a template to build new projects or adapt the pattern to existing ones.

> **Note:** This demo is engineered for simplicity. In a real application, Java paths should be hardcoded in your build scripts and config files rather than centralized through `env.bat`.

## What This Project Does

A .NET Framework console app (`LoggerDemo.exe`) calls Java's log4j logging library and a custom Java class (`JavaClass`) through JNBridge proxy DLLs. JNBridge generates .NET wrapper classes that transparently marshal calls to an embedded JVM via shared memory.

## Project Structure (3-folder separation)

```
LoggerDemoNew/
├── env.bat                  # Java paths — edit this for your machine
├── buildAndRunSharedMem.bat  # Orchestrator: shared-memory mode
├── buildAndRunTCP.bat       # Orchestrator: TCP mode (separate Java process)
├── LoggerDemo.sln           # VS solution
│
├── Java Side/               # Java source code + runtime JARs
│   ├── loggerDemo/
│   │   └── JavaClass.java   # Custom Java class (user code goes here)
│   ├── jnbcore.jar          # JNBridge Java-side runtime (REQUIRED)
│   ├── bcel-6.10.0.jar      # BCEL library for shared-memory transport (REQUIRED)
│   ├── log4j.jar            # Log4j 1.x (app dependency — this is what we're calling)
│   ├── log4j-core.jar       # Log4j core
│   ├── classWhiteList.txt   # Runtime class whitelist
│   ├── jnbcore_tcp_no_security.properties  # TCP mode config (port 8085, no SSL)
│   └── start Java side.bat  # Manual start for Java side in TCP mode
│
├── ProxyGen/                # Proxy generation tooling (runs at build time only)
│   ├── Build.bat            # Compiles Java → JAR → generates .NET proxy DLL
│   ├── GenClassList.bat     # Discovers available classes from JARs → writes classList.txt
│   ├── classList.txt        # Lists Java classes to generate .NET proxies for
│   ├── jnbproxy.exe         # JNBridge proxy generator tool
│   ├── jnbpcommon.dll       # jnbproxy dependency
│   ├── JNBShare.dll         # jnbproxy dependency
│   ├── jnbauth_x64.dll     # jnbproxy dependency
│   └── JNBSharedMem_x64.dll # jnbproxy dependency
│
└── LoggerDemo/              # .NET project (SDK-style, targets net48)
    ├── Program.cs           # C# entry point — calls Java classes via proxies
    ├── App.config           # JNBridge shared-memory config (JVM path, classpath)
    ├── App.tcp.config       # JNBridge TCP config (jtcp, localhost:8085)
    ├── LoggerDemo.csproj    # References JNBShare.dll + logging.dll (proxy)
    ├── logging.dll          # Generated proxy DLL (created by ProxyGen/Build.bat)
    ├── JNBShare.dll         # JNBridge .NET runtime (REQUIRED at runtime)
    ├── jnbauth_x64.dll      # Auth (copied to output)
    ├── jnbauth_x86.dll      # Auth (copied to output)
    ├── JNBSharedMem_x64.dll  # Shared memory transport (copied to output)
    └── JNBSharedMem_x86.dll  # Shared memory transport (copied to output)
```

## How the Build Pipeline Works

`buildAndRunSharedMem.bat` runs three steps:

### Step 1: `ProxyGen/Build.bat` (Java compilation + class list + proxy generation)
1. **javac** compiles `Java Side/loggerDemo/JavaClass.java` → `.class`
2. **jar** packages the `.class` into `Java Side/loggerDemo.jar`
3. **jnbproxy.exe /ls** scans all JARs and writes discovered classes to `classList.txt`
4. **jnbproxy.exe** reads `classList.txt` and generates `logging.dll` — a .NET assembly containing C# wrapper classes for each listed Java class
5. Copies `logging.dll` to `LoggerDemo/` so the .csproj can reference it

### Step 2: `dotnet build -c Release`
- Builds the C# project, which references `JNBShare.dll` (JNBridge runtime) and `logging.dll` (generated proxies)
- The .csproj copies all runtime DLLs and JARs to `bin/Release/net48/`

### Step 3: Config generation
- Reads `App.config` as XML, substitutes `jvm64`/`jvm32` attributes with the paths from `env.bat`, and writes the result to `bin/Release/net48/LoggerDemo.exe.config`

## Generating a Class List from JARs

Before you can generate proxies, you need to know what Java classes are available. `ProxyGen/GenClassList.bat` automates this using jnbproxy's `/ls` flag.

**How it works:** The `/ls` flag tells jnbproxy to scan the JARs on its `/cp` classpath and output a class list to `classList.txt` instead of generating proxy DLLs. This is the command-line equivalent of browsing classes in the JNBProxy GUI.

**Workflow for a new project:**
1. Place your JARs in `Java Side/`
2. Update `GenClassList.bat` to include your JARs in the `/cp` flag
3. Run `GenClassList.bat` — it writes all discoverable classes to `classList.txt`
4. **Edit `classList.txt`** — remove classes you don't need, keep only the ones you want to call from .NET
5. Run `Build.bat` to generate the proxy DLL from your curated class list

**The `/ls` flag:** Adding `/ls` to any jnbproxy command switches it from proxy generation mode to class list discovery mode. All other flags (`/cp`, `/jp`, `/bp`, `/jvm`, etc.) work the same — they tell jnbproxy where to find the JARs to scan.

```
jnbproxy.exe /ls /ns /pd n2j /cp "mylib.jar;dep.jar" /f "classList.txt" /d . /n MyProxies /jp "jnbcore.jar" /bp "bcel-6.10.0.jar" /pro s /jvm "path\jvm.dll"
```

This is especially useful when working with large Java libraries where you don't know the exact class names upfront.

## TCP Mode (`buildAndRunTCP.bat`)

An alternative to shared-memory mode. Instead of embedding the JVM in-process, the Java side runs as a separate process and the .NET side connects over TCP.

### How it differs from `buildAndRunSharedMem.bat`

| | Shared Memory (`buildAndRunSharedMem.bat`) | TCP (`buildAndRunTCP.bat`) |
|---|---|---|
| **Transport** | In-process shared memory | TCP socket (port 8085) |
| **Java process** | Embedded JVM (automatic) | Separate process (started explicitly) |
| **Config file** | `App.config` (`scheme="sharedmem"`) | `App.tcp.config` (`scheme="jtcp"`) |
| **JVM paths needed in config** | Yes (`jvm64`/`jvm32`) | No (Java side manages its own JVM) |

### TCP-specific files

- **`LoggerDemo/App.tcp.config`** — .NET config with `scheme="jtcp"`, `host="localhost"`, `port="8085"`. Copied over `LoggerDemo.exe.config` in the output directory at build time.
- **`Java Side/jnbcore_tcp_no_security.properties`** — Java-side config: TCP on port 8085, no SSL, class whitelist enabled.
- **`Java Side/start Java side.bat`** — Convenience script to start the Java side manually (same command that `buildAndRunTCP.bat` runs).

### `buildAndRunTCP.bat` steps

1. **Build** — Runs `ProxyGen/Build.bat` (same as shared-memory)
2. **dotnet build** — Builds the .NET project (same as shared-memory, uses `App.config`)
3. **Config swap** — Copies `App.tcp.config` over `bin/Release/net48/LoggerDemo.exe.config`
4. **Start Java side** — Launches `java ... JNBMain` in a separate console window
5. **Run .NET app** — Runs `LoggerDemo.exe` which connects via TCP
6. **Cleanup** — Kills the Java side window after the demo exits

### Changing the port

Update both files to match:
- `Java Side/jnbcore_tcp_no_security.properties` — `javaSide.port=8085`
- `LoggerDemo/App.tcp.config` — `port="8085"`

### Enabling SSL

1. In `jnbcore_tcp_no_security.properties`, set `javaSide.useSSL=true` and configure keystore/truststore properties
2. In `App.tcp.config`, change `scheme="jtcp"` to `scheme="jtcp_ssl"` and add SSL certificate attributes

For more details on SSL, TCP, and other configuration options, see the JNBridge knowledge base:
- https://jnbridge.com/support/knowledge-base/anatomy-of-a-net-project-that-calls-java-shared-memory-bridge
- https://jnbridge.com/support/knowledge-base/changing-to-tcp-configuration-ssl-whitelisting-startup

### Adapting host/port for a new project

When adapting this project, update the TCP host/port in the adaptation checklist (step 6 equivalent for TCP):
- `LoggerDemo/App.tcp.config` — `host` and `port` attributes
- `Java Side/jnbcore_tcp_no_security.properties` — `javaSide.port`

## Key Configuration Files

### `ProxyGen/classList.txt` — What gets proxied
Each line: `fully.qualified.ClassName r` (the `r` means reference type). Only classes listed here get .NET proxy wrappers generated. This file can be hand-written or auto-generated using `GenClassList.bat`.

```
org.apache.log4j.Category r
org.apache.log4j.BasicConfigurator r
loggerDemo.JavaClass r
java.lang.Class r
java.lang.Object r
```

### `LoggerDemo/App.config` — Runtime JNBridge configuration
Configures shared-memory transport with paths to the JVM and Java classpath:
- `scheme="sharedmem"` — uses in-process shared memory (no separate Java process needed)
- `jvm64` / `jvm32` — paths to jvm.dll for 64-bit and 32-bit
- `jnbcore`, `bcel` — JNBridge runtime JARs
- `classpath` — Java JARs available at runtime (the .csproj copies these to output, so simple filenames work)
- `jvmOptions.0` — JVM flags (here: bootclasspath for log4j)

### `LoggerDemo/LoggerDemo.csproj` — .NET project
SDK-style project targeting `net48`. Key patterns:
- `<Reference>` for `JNBShare.dll` and `logging.dll` (the proxy)
- `<Content>` with `CopyToOutputDirectory` for native DLLs (`jnbauth_*`, `JNBSharedMem_*`)
- `<None>` with `Link` + `CopyToOutputDirectory` for Java-side JARs (copied from `Java Side/` to output)

## How C# Calls Java

In `Program.cs`, Java classes are used directly as if they were .NET types:

```csharp
using org.apache.log4j;      // from logging.dll (generated proxy)
using loggerDemo;             // from logging.dll (generated proxy)

BasicConfigurator.configure();                              // Java static method
Category cat = Category.getInstance("MyApp");               // Java static method
cat.info(new JavaString("Hello from .NET"));                // Java instance method
JavaClass javaClass = new JavaClass();                      // Java constructor
javaClass.doIt();                                           // Java instance method
```

Note: Java `String` parameters must be wrapped with `java.lang.JavaString` (from JNBShare.dll).

## Prerequisites

- **Java 8 JDK/JRE** — set `JAVA_HOME` in `env.bat` to match your install
- **.NET Framework 4.8 targeting pack** — for `dotnet build` with `net48`
- **JNBridge Pro v12.0 license** — the ProxyGen tools are licensed

## Adapting This to a New Project

To call different Java classes from .NET:

1. **Edit `env.bat`** — Set `JAVA_HOME` to your JDK install path (and optionally `JVM_DLL_32` for 32-bit). All batch scripts read Java paths from this single file. `App.config` still contains default JVM paths for VS users, but the orchestrator scripts (`buildAndRunSharedMem.bat`) override them from `env.bat` at build time.
2. **Java Side:** Add your `.java` source files and any dependency JARs
3. **ProxyGen/GenClassList.bat:** Update `/cp` to include your JARs, run it to discover available classes
4. **ProxyGen/classList.txt:** Edit the generated list — keep only the classes you need from .NET
5. **ProxyGen/Build.bat:** Update the `javac -cp` and `jnbproxy /cp` to include your JARs
6. **LoggerDemo/App.config:** Update `classpath` and any `jvmOptions` for your JARs
7. **LoggerDemo/LoggerDemo.csproj:** Add `<None>` entries for any new JARs that need to be copied to output
8. **LoggerDemo/Program.cs:** Use the generated proxy classes with `using` statements matching the Java package names

### Common jnbproxy flags (in Build.bat)
| Flag | Meaning |
|------|---------|
| `/ls` | List mode: output class list to classList.txt instead of generating proxies |
| `/ns` | No splash screen |
| `/pd n2j` | Proxy direction: .NET-to-Java |
| `/cp "jar1;jar2"` | Java classpath for proxy generation |
| `/f "classList.txt"` | Input file listing classes to proxy |
| `/d .` | Output directory for generated DLL |
| `/n logging` | Output DLL name (produces `logging.dll`) |
| `/jp "jnbcore.jar"` | JNBridge core JAR |
| `/bp "bcel.jar"` | BCEL JAR path |
| `/pro s` | Protocol: shared memory |
| `/jvm "path\jvm.dll"` | JVM path for proxy generation |

### Troubleshooting
- **JVM path errors:** Edit `env.bat` at the project root — set `JAVA_HOME` to match your Java install. The orchestrator scripts override `App.config` JVM paths at build time.
