0

I have a application which is started via command line like java -jar MyAssembledJarWithAllDep.jar -foo bar

I am using weld.se to be able to use the jakarta ee cdi specification. Furthermore I am using the apache cli tool to parse the comman line arguments.

Here are my maven imports:

        <dependency>
            <groupId>jakarta.enterprise</groupId>
            <artifactId>jakarta.enterprise.cdi-api</artifactId>
            <version>3.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.weld.se</groupId>
            <artifactId>weld-se</artifactId>
            <version>2.4.6.Final</version>
        </dependency>

        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.4</version>
        </dependency>

That's how I initialize the container:

    public static void main(String[] args) {
        Weld weld = new Weld();
        WeldContainer container = weld.initialize();
        container.select(MyRunnerClass.class).get().run(args);
        container.shutdown();
    }

I could do the following:

public void run(String[] args) {
   CommandLineParser clp = new CommandLineParser(args);
   clp.parse();

But since I want to use the full support of cdi, I cannot the object since I created it myself! So how do I pass the arguments to the container so that weld can create the CommandLineParser himself with the needed arguments?

Wumba
  • 99
  • 1
  • 12
  • 1
    Important side note - Jakarta CDI 3.0 is Weld 4, please update those dependencies accordingly. – Siliarus Apr 15 '21 at 14:50
  • But how do I initialize the container then? The code above will not work then. – Wumba Apr 15 '21 at 14:54
  • What do you mean? You will do it just like you do it now. Only replace Weld 2 (which is unsupported and is CDI 1.2) with Weld 4 which is an implementation of CDI 3. – Siliarus Apr 15 '21 at 14:57
  • There is no such thing like weld-se v4, weld-se latest version is 3. I tried a bit around a found that there is weld-se-shaded which provides the necessary dependencies for cdi with java se. That one is available in version 4. – Wumba Apr 15 '21 at 15:07
  • 1
    The artifact name for shaded artifact changed in between Weld 2 and Weld 3. You want to use `weld-se-shaded` artifact now. Documented here - https://docs.jboss.org/weld/reference/latest/en-US/html_single/#_shaded_jars_name_change – Siliarus Apr 15 '21 at 15:14
  • Perhaps you should externalize configuration info rather than passing command-line arguments. At runtime, use JNDI to access the needed info. – Basil Bourque Apr 15 '21 at 16:11

2 Answers2

3

Note that Weld already makes the command-line arguments available for injection.

Laird Nelson
  • 15,321
  • 19
  • 73
  • 127
  • This seems to be a preety cool feature, but I don't get it running, the injected params are always null. Have you tried it yourself? Do you have any idea? – Wumba Apr 16 '21 at 08:28
  • 2
    @Wumba This seems to work only, if you use weld's StartMain instead of initializing your own container. However, under the hood there's a ParametersFactory, which gets the params from the public static field StartMain.PARAMETERS. So, you can initialize this via `StartMain.PARAMETERS = args` as the first thing in your own main method, and then injection shall work. – mtj Apr 17 '21 at 05:55
0

I am not familiar with apache cli tools so I am assuming CommandLineParser is not a bean on its own and you want to turn it into a bean. In that case you need to provide a producer method which can make use of any local metadata in creation of the object.

The following method is a producer method and needs to be placed in another bean class for it to work (see CDI specification for more details):

@Produces
@ApplicationScoped // or any other scope that you want to use for the bean!
public CommandLineParser produceCmdLineParser() {
  String[] args = retrieveArgs(); // grab arguments from your main class or other place
  return new CommandLineParser(args);
}

The above producer method will then be invoked by Weld (do not invoke it manually) when you ask the CDI container for bean of type CommandLineParser via standard or dynamic injection.

Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • How do I grab the arguments from the main class? At this point I am rather confused by CDI and might not see the obvious. – Wumba Apr 15 '21 at 15:10
  • Those args are the main method args, right? In that case it has nothing to do with CDI itself, it is plain Java. Just place them in an accessible field, or use setter method on a bean that holds this producer. Any such thing would do. – Siliarus Apr 15 '21 at 15:18