Embed crash in regular jar and open shell when you run the jar?

111 views
Skip to first unread message

Steve Storck

unread,
Apr 23, 2016, 11:44:19 AM4/23/16
to CRaSH User Group
I have been looking for examples of the simplest (and thinnest) way of embedding CRaSH in a regular jar application.  I also want to be able to invoke the shell when starting up the application so that the user does not have to invoke any commands to access the jar.  Can anyone please point me in the right direction?

Thanks,
Steve

Julien Viet

unread,
Apr 23, 2016, 3:45:33 PM4/23/16
to crash...@googlegroups.com
On Apr 23, 2016, at 5:44 PM, Steve Storck <stev...@gmail.com> wrote:

I have been looking for examples of the simplest (and thinnest) way of embedding CRaSH in a regular jar application.

I gave you pointers a few days ago, can you tell us what went wrong ?

  I also want to be able to invoke the shell when starting up the application so that the user does not have to invoke any commands to access the jar.  Can anyone please point me in the right direction?

you want to execute prepared commands without a prompt ?


Thanks,
Steve

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Steve Storck

unread,
Apr 23, 2016, 3:57:23 PM4/23/16
to CRaSH User Group
I'm sorry if I implied that you didn't help.  I will be using your suggestion, and it was exactly the help that I need.  I want to launch my app and use the example that you provided to parse command line arguments, and I want the shell to be active at the command line where I invoke the jar so that people can interact with the application, but not have to launch the shell separately.  All of the documentation that I have seen shows that you must telnet or ssh into the shell, or invoke the shell separately on the command line.  I am sure that I am misunderstanding it, but I don't think that I have found the right examples.  Thanks for your time!

Cheers,
Steve

Steve Storck

unread,
Apr 24, 2016, 3:58:12 PM4/24/16
to CRaSH User Group
Maybe it would be helpful if I describe the workflow that I want:
  1. User starts up my application jar with some optional arguments
  2. Application uses CRaSH to parse command line arguments
    • You have already given me a good example to handle this part
  3. Application starts up various process threads
  4. Application starts up CRaSH shell for users to interact with the process threads by using commands that I provide
    • This is the part that I am curious about.  I would like the application to start the shell directly on the console where the user invoked the jar and not have to manually connect via telnet or ssh.
  5. The user eventually exits the shell, which returns to the application's workflow so that it can shut the application down properly.

Thanks again,

Steve


On Saturday, April 23, 2016 at 3:45:33 PM UTC-4, Julien Viet wrote:

Steve Storck

unread,
May 1, 2016, 1:12:11 PM5/1/16
to CRaSH User Group
Hi, Julien.  At this point, I'm still at a loss.  If I already have an application in a jar, but I want to be able to start the jar from the command line with java -jar MyApplication.jar.  It should run as normal, and also immediately open the CRaSH shell.  I either haven't been able to find examples for how to do this, or I haven't quite understood how that is achieved.

Julien Viet

unread,
May 1, 2016, 1:22:38 PM5/1/16
to crash...@googlegroups.com
can you provide a github project someone (eventually me) can clone to look at and help ?

Steve Storck

unread,
May 1, 2016, 7:17:51 PM5/1/16
to CRaSH User Group
Julien,

Yes.  I'm currently workign on a Camel Standalone application.  In what's committed, I have some commands (I know that I'll have to edit the usage and man annotation values) but I don't have anything that attempts to integrate the shell into the application yet.  I am also worried that I will have two "trace" commands on the classpath.  One is meant for CLI arguments to the application, and the other is meant to be able to change that value in the shell if desired.  They reside in the "cli" and "shell" packages, respectively.  If necessary, I'll tackle that later, but I would like a couple of pointers in getting the shell up and running when I launch the app, as I described.  Thank you very much for your time and advice and expertise.

Steve Storck

unread,
May 3, 2016, 5:49:48 PM5/3/16
to CRaSH User Group
I added some spring (java config) configuration for the SpringBootstrap stuff to the github repo that I linked above.

Steve Storck

unread,
May 4, 2016, 3:34:44 PM5/4/16
to CRaSH User Group
Julien,

Well, it looks like just creating the SpringBootstrap instance causes it to open the shell when I execute the jar.  That was way easier than I thought.  Now, it's just a matter of doing the right things with the commands.

Incidentally, I was able to override the login.groovy command by including my own custom version in src/groovy/commands/base, and then:

1. Using this filter in the shade plugin configuration:
<filters>
    <filter>
        <artifact>org.crashub:crash.shell</artifact>
        <excludes>
            <exclude>crash/commands/base/login.groovy</exclude>
        </excludes>
    </filter>
</filters>

2. Using this resources element in the build section:
<resources>
    <resource>
        <directory>src/main/groovy/commands</directory>
        <targetPath>crash/commands</targetPath>
        <filtering>false</filtering>
    </resource>
</resources>

That's pretty cool!

Steve Storck

unread,
May 4, 2016, 3:37:57 PM5/4/16
to CRaSH User Group
I apologize for the formatting in the previous message.  Anyway, I have pushed what I have at the github repo: https://github.com/Steve973/camel-standalone

Have a look if you have some time, and feel free to make recommendations if I've done some awful things! ;)

Thanks,
Steve

Julien Viet

unread,
May 5, 2016, 12:44:11 PM5/5/16
to crash...@googlegroups.com
Hi,

I’ve just tried it and it looks good from first sight :-)

my advice : add in the readme instruction for trying:

> mvn package
java -jar target/camel-standalone-2.17.0.jar 

I tried “context-info” but it does not work "Could not compile command script context-info

is it expected ?

Steve973

unread,
May 5, 2016, 1:55:49 PM5/5/16
to crash...@googlegroups.com
Julien,

Thanks for checking it out.  Yes, the commands are completely broken at the moment.  I haven't quite gotten the same error that you are getting.  Are you using java 1.8?  For me, I get null pointer exceptions because I have not retrieved the proper bean that most of the information is retrieved from.  When I am really read to get some feedback, the whole code base will be thoroughly tested and the readme will be quite detailed.  But, along the way, I will send you some updates to check out the progress.  It might serve as a helpful example to some other people.  And if it is indeed eventually included with the camel distribution, it will be very readily available.

Thanks again,
Steve

--
Vous recevez ce message, car vous êtes abonné à un sujet dans le groupe Google Groupes "CRaSH User Group".
Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/crash-users/96CXU3HBpwk/unsubscribe.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse crash-users...@googlegroups.com.

Julien Viet

unread,
May 5, 2016, 2:47:33 PM5/5/16
to crash...@googlegroups.com
On May 5, 2016, at 7:55 PM, Steve973 <stev...@gmail.com> wrote:

Julien,

Thanks for checking it out.  Yes, the commands are completely broken at the moment.  I haven't quite gotten the same error that you are getting.  Are you using java 1.8? 

yes I am

For me, I get null pointer exceptions because I have not retrieved the proper bean that most of the information is retrieved from.  When I am really read to get some feedback, the whole code base will be thoroughly tested and the readme will be quite detailed.  But, along the way, I will send you some updates to check out the progress.  It might serve as a helpful example to some other people.  And if it is indeed eventually included with the camel distribution, it will be very readily available.

is Claus Ibsen aware of this ? he has done CRaSH integration with Camel as far as I remember

Steve973

unread,
May 5, 2016, 3:16:10 PM5/5/16
to crash...@googlegroups.com

Yes. I have talked with him about this module. He seemed to be interested.

Steve Storck

unread,
May 5, 2016, 4:13:14 PM5/5/16
to CRaSH User Group
In src/main/java/org/apache/camel/standalone/config/StandaloneConfig.java, I am setting up the Spring bean configuration.  How do I make the other Spring beans available to the command context so that I can use those instances within the command code?

Thanks,
Steve

Julien Viet

unread,
May 5, 2016, 4:43:17 PM5/5/16
to crash...@googlegroups.com

Steve Storck

unread,
May 5, 2016, 6:09:18 PM5/5/16
to CRaSH User Group
I tried, but I am not using SpringBoot.  Rather, I am using a @Configuration class.  When I try to get the 'spring.beanfactory' attribute, it is null.  Actually, attributes is empty.  I am not sure how to wire it up properly for the attributes of the context to become populated.

Steve Storck

unread,
May 6, 2016, 6:10:15 PM5/6/16
to CRaSH User Group
I have this configuration class:
@Configuration
public class StandaloneConfig {
    @Bean(name = "springBootstrap")
    @Scope(value = "singleton")
    public SpringBootstrap springBootstrap() {
        return new SpringBootstrap();
    }

    @Bean(name = "StandaloneRunner")
    public StandaloneRunner standaloneRunner() {
        return StandaloneRunner.getInstance();
    }
}

And I have this in my main method, along with a method to configure the SpringBootstrap:
public static void main(String... args) throws Exception {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StandaloneConfig.class);
    configureSpringBootstrap(ctx);
    ctx.start();
}

private static void configureSpringBootstrap(ApplicationContext ctx) {
    SpringBootstrap bootstrap = ctx.getBean(SpringBootstrap.class);
    bootstrap.setBeanFactory(ctx.getAutowireCapableBeanFactory());
    bootstrap.setBeanClassLoader(ctx.getClassLoader());
    bootstrap.setCmdMountPointConfig("classpath:/commands");
    bootstrap.setConfMountPointConfig("classpath:/camel-standalone-crash.properties");
    Properties properties = new Properties();
    properties.put("crash.vfs.refresh_period", "1");
    properties.put("crash.auth", "simple");
    properties.put("crash.auth.simple.username", "admin");
    properties.put("crash.auth.simple.password", "admin");
    bootstrap.setConfig(properties);
}

Here is one of my commands, from src/main/groovy/commands/context-info.groovy:
class contextInfo {
    private def String INDENT = '  '
    StandaloneRunner standalone

    @Command
    public void main(InvocationContext context, @Argument String name) {
        BeanFactory factory = context.attributes['spring.beanfactory']
        standalone = factory.getBean StandaloneRunner
        if (!name) {
            printAllContextInfo()
        } else {
            out.println 'Context info:'
            printContextInfo 2, standalone.contexts[name]
        }
    }
It is not compiled, but copied to the jar at /commands.

When I launch, it appears that it initializes twice, and the factory variable is null:
May 06, 2016 6:07:32 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO
: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@64bf3bbf: startup date [Fri May 06 18:07:32 EDT 2016]; root of context hierarchy
May 06, 2016 6:07:32 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO
: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6d3af739: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,standaloneConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,StandaloneRunner,springBootstrap]; root of factory hierarchy
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property vfs.refresh_period=1 from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=GroovyLanguageProxy,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=JavaLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=ScriptLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property auth.simple.username=admin from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property auth.simple.password=admin from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=GroovyLanguageProxy,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=JavaLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=ScriptLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]
SLF4J
: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J
: Defaulting to no-operation (NOP) logger implementation
SLF4J
: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
May 06, 2016 6:07:33 PM org.crsh.standalone.CRaSH main
INFO
: conf mounts: classpath:/crash/
May 06, 2016 6:07:33 PM org.crsh.standalone.CRaSH main
INFO
: cmd mounts: classpath:/crash/commands/
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property auth.simple.username=admin from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property auth.simple.password=admin from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginLifeCycle configureProperty
INFO
: Configuring property vfs.refresh_period=1 from properties
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=GroovyLanguageProxy,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=JavaLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=ScriptLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO
: Loaded plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=GroovyLanguageProxy,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=JavaLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=ScriptLanguage,interface=Language]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
May 06, 2016 6:07:33 PM org.crsh.plugin.PluginManager getPlugins
INFO
: Initialized plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]

It brings up my custom banner and prompt, and when I invoke the command I listed above, this is the result:
context-info: exception: Cannot invoke method getBean() on null object
standalone
-shell (main)>May 06, 2016 6:07:39 PM org.crsh.shell.impl.command.CRaSHProcess execute
SEVERE
: Error while evaluating request 'context-info' context-info: exception: Cannot invoke method getBean() on null object
java
.lang.NullPointerException: Cannot invoke method getBean() on null object
        at org
.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
        at org
.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
        at org
.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
        at org
.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
        at org
.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
        at org
.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org
.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
        at contextInfo
.main(context-info:23)
        at sun
.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun
.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun
.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java
.lang.reflect.Method.invoke(Method.java:497)
        at org
.crsh.cli.impl.lang.MethodDescriptor$1.invoke(MethodDescriptor.java:164)
        at org
.crsh.cli.impl.lang.MethodDescriptor$1.invoke(MethodDescriptor.java:106)
        at org
.crsh.lang.impl.java.ProducerCommandMatch$1.close(ProducerCommandMatch.java:117)
        at org
.crsh.shell.impl.command.pipeline.CommandInvokerAdapter.close(CommandInvokerAdapter.java:296)
        at org
.crsh.shell.impl.command.pipeline.PipeLine.close(PipeLine.java:106)
        at org
.crsh.shell.impl.command.spi.CommandInvoker.invoke(CommandInvoker.java:52)
        at org
.crsh.shell.impl.command.CRaSHCommandProcess.doInvoke(CRaSHCommandProcess.java:39)
        at org
.crsh.shell.impl.command.CRaSHProcess.execute(CRaSHProcess.java:60)
        at org
.crsh.shell.impl.async.AsyncProcess$2.call(AsyncProcess.java:207)
        at org
.crsh.shell.impl.async.AsyncProcess$2.call(AsyncProcess.java:177)
        at java
.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java
.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java
.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java
.lang.Thread.run(Thread.java:745)


Do you have any idea what I'm doing wrong?

Thanks,
Steve
Reply all
Reply to author
Forward
0 new messages