[ACCEPTED]-Dealing with command line arguments and Spring-command-line

Accepted answer
Score: 40

Two possibilities I can think of.

1) Set 10 a static reference. (A static variable, although 9 typically frowned upon, is OK in this case, because 8 there can only be 1 command line invocation).

public class MyApp {
  public static String[] ARGS; 
  public static void main(String[] args) {
    ARGS = args;
      // create context
  }
}

You 7 can then reference the command line arguments 6 in Spring via:

<util:constant static-field="MyApp.ARGS"/>

Alternatively (if you are 5 completely opposed to static variables), you 4 can:

2) Programmatically add the args to 3 the application context:

 public class MyApp2 {
   public static void main(String[] args) {
     DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // Define a bean and register it
     BeanDefinition beanDefinition = BeanDefinitionBuilder.
       rootBeanDefinition(Arrays.class, "asList")
       .addConstructorArgValue(args).getBeanDefinition();
     beanFactory.registerBeanDefinition("args", beanDefinition);
     GenericApplicationContext cmdArgCxt = new GenericApplicationContext(beanFactory);
     // Must call refresh to initialize context 
     cmdArgCxt.refresh();

     // Create application context, passing command line context as parent
     ApplicationContext mainContext = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS, cmdArgCxt);

     // See if it's in the context
     System.out.println("Args: " + mainContext.getBean("args"));
   }

   private static String[] CONFIG_LOCATIONS = new String[] {
     "applicationContext.xml"
   };

 }

Parsing the command 2 line arguments is left as an exercise to 1 the reader.

Score: 7

Have a look at my Spring-CLI library - at 5 http://github.com/sazzer/spring-cli - as one way of doing this. It gives you 4 a main class that automatically loads spring 3 contexts and has the ability to use Commons-CLI 2 for parsing command line arguments automatically 1 and injecting them into your beans.

Score: 7

Starting from Spring 3.1 there is no need 12 in any custom code suggested in other answers. Check 11 CommandLinePropertySource, it provides a natural way to inject CL 10 arguments into your context.

And if you are 9 a lucky Spring Boot developer you could 8 simplify your code one step forward leveraging 7 the fact that SpringApplication gives you the following:

By 6 default class will perform the following 5 steps to bootstrap your application:

...

Register 4 a CommandLinePropertySource to expose command 3 line arguments as Spring properties

And if 2 you are interested in the Spring Boot property 1 resolution order please consult this page.

Score: 5

You can also pass an Object array as a second 2 parameter to getBean which will be used as arguments 1 to the constructor or factory.

public static void main(String[] args) {
   Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
Score: 3

Consider the following class:

public class ExternalBeanReferneceFactoryBean 
    extends AbstractFactoryBean
    implements BeanNameAware {

    private static Map<String, Object> instances = new HashMap<String, Object>();
    private String beanName;

    /**
     * @param instance the instance to set
     */
    public static void setInstance(String beanName, Object instance) {
        instances.put(beanName, instance);
    }

    @Override
    protected Object createInstance() 
        throws Exception {
        return instances.get(beanName);
    }

    @Override
    public Class<?> getObjectType() {
        return instances.get(beanName).getClass();
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

}

along with:

/**
 * Starts the job server.
 * @param args command line arguments
 */
public static void main(String[] args) {

    // parse the command line
    CommandLineParser parser = new GnuParser();
    CommandLine cmdLine = null;
    try {
        cmdLine = parser.parse(OPTIONS, args);
    } catch(ParseException pe) {
        System.err.println("Error parsing command line: "+pe.getMessage());
        new HelpFormatter().printHelp("command", OPTIONS);
        return;
    }

    // create root beanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // register bean definition for the command line
    ExternalBeanReferneceFactoryBean.setInstance("commandLine", cmdLine);
    beanFactory.registerBeanDefinition("commandLine", BeanDefinitionBuilder
        .rootBeanDefinition(ExternalBeanReferneceFactoryBean.class)
        .getBeanDefinition());

    // create application context
    GenericApplicationContext rootAppContext = new GenericApplicationContext(beanFactory);
    rootAppContext.refresh();

    // create the application context
    ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { 
        "/commandlineapp/applicationContext.xml"
    }, rootAppContext);

    System.out.println(appContext.getBean("commandLine"));

}

0

Score: 1

Here is an example to boot strap spring 5 for a Main method, simply grab the passed 4 params as normal then make the function 3 you call on your bean (in the case deployer.execute()) take 2 them as Strings or via any format you feel 1 suitable.

public static void main(String[] args) throws IOException, ConfigurationException {
    Deployer deployer = bootstrapSpring();

    deployer.execute();
}

private static Deployer bootstrapSpring()
{
    FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext("spring/deployerContext.xml");

    Deployer deployer = (Deployer)appContext.getBean("deployer");
    return deployer;
}
Score: 0

I'm not sure what you are trying to achieve 8 exactly, maybe you can add some details 7 on what the command and the arguments will 6 look like, and what outcome you expect from 5 your application.

I think this is not what 4 you need, but it might help other readers: Spring 3 supports receiving properties from the command 2 line using double hyphen (e.g. java -jar app.jar --my.property="Property Value" Have a look 1 at this documentation for more information: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-command-line-args

More Related questions