使用Procrun(Apache JSVC)部署含WELD容器的Java Windows服务报错求助
Hey there, let's break down how to fix this WELD context/classpath issue when running your app as a Windows service with Procrun!
Common Causes & Fixes
1. Mismatched Working Directory & Classpath
When running via gradle run, your app uses the project's root directory as the working path, and Gradle handles the full classpath automatically. But Procrun runs services with a default system working directory (like C:\Windows\System32) and won't inherit Gradle's classpath setup.
Fix:
- In your Procrun configuration, explicitly set:
--WorkingDirectoryto your app's root folder (where your JARs/configs live)--Classpathto include your app JAR and all dependencies. If you use a fat JAR (via Gradle Shadow plugin), just point to that single JAR.
Example Procrun command snippet:
prunsrv.exe //IS//LogReaderService ^ --DisplayName="Log Reader Service" ^ --WorkingDirectory="C:\path\to\your\app" ^ --Classpath="C:\path\to\your\app\build\libs\logreader-fat.jar" ^ --StdOutput="C:\path\to\your\app\logs\stdout.log" ^ --StdError="C:\path\to\your\app\logs\stderr.log"
2. WELD Initialization Timing/Scope
When running as a service, your app's entry point might differ from the gradle run flow. If WELD is initialized only in your main method but Procrun uses a dedicated start method for service bootstrapping, the container might never be properly spun up.
Fix:
Create a service starter class with explicit start/stop methods (required by Procrun) that handle WELD initialization and shutdown:
public class LogReaderServiceStarter { private static Weld weldContainer; private static WeldContainer activeContainer; public static void start(String[] args) { // Initialize WELD explicitly when the service starts weldContainer = new Weld(); activeContainer = weldContainer.initialize(); // Retrieve your core service bean and start processing LogProcessor processor = activeContainer.select(LogProcessor.class).get(); processor.startReadingLogs(); } public static void stop(String[] args) { // Clean up WELD properly when the service stops if (activeContainer != null) { activeContainer.shutdown(); } if (weldContainer != null) { weldContainer.shutdown(); } } }
Then update your Procrun config to use this class:
--StartClass=com.yourpackage.LogReaderServiceStarter ^ --StartMethod=start ^ --StopClass=com.yourpackage.LogReaderServiceStarter ^ --StopMethod=stop
3. Missing WELD Configuration Files
WELD relies on beans.xml (in META-INF) to scan for beans. If this file isn't included in your packaged JAR, or Procrun can't access it due to working directory issues, WELD won't find your components.
Fix:
- Ensure your Gradle build copies
src/main/resources/META-INF/beans.xmlinto the final JAR. If using the Shadow plugin, add this to yourbuild.gradle:
shadowJar { from('src/main/resources') { into 'META-INF' } mergeServiceFiles() }
4. Debug with Procrun Logs
You're flying blind without seeing the exact error WELD throws. Procrun lets you capture stdout/stderr to files—use this to get detailed stack traces.
Fix:
Add these lines to your Procrun config (as shown earlier) and check the logs after starting the service:
--StdOutput="C:\path\to\your\app\logs\stdout.log" ^ --StdError="C:\path\to\your\app\logs\stderr.log"
Look for lines like WELD-001408: Unsatisfied dependencies for type... or ClassNotFoundException—these will point directly to the classpath/context issue.
Quick Checklist
- Package your app as a fat JAR with all dependencies (including WELD)
- Set Procrun's
WorkingDirectoryto your app's folder - Use a dedicated service starter class with explicit WELD init/shutdown
- Verify
beans.xmlis present in the JAR'sMETA-INFfolder - Check Procrun logs for specific WELD errors
内容的提问来源于stack exchange,提问作者Szymon Dudziak

