Spring Shell - usage and execution - java

I want to integrate Spring Shell within a spring boot application. I am able to execute the examples from the official git-repo. But when migrating the example code to my own project that is very very similar to this code, my individual shell is not shown or usable. Instead the default Spring Shell splash is shown is usable:
<SpringShell ASCII-Art>
1.1.0.RELEASE
Welcome to Spring Shell. For assistance press or type "hint" then hit ENTER
spring-shell>
Compilation gives no errors, but the individual sample #component marked classes are not used. All annotations are properly set. A standard loader outside is existent. I am not executing the code in an IDE.
Although the documentation (chapter 3.5) tells, that the components are automatically collected as far as i understood.
So my question is more or less how to setup the usage better than
this:
public class Main {
public static void main(String[] args) throws Exception {
Bootstrap.main(args);
}
}
And to defeat the default splash!

That comment in the documentation is a bit misleading (I'll change it).
For your components to be picked up, they need to be on the classpath AND you'll need to scan for them somehow.
See for example how in the Spring XD project, there is a scan for the org.springframework.xd.shell package. You need to do something similar for your own package.

SOLUTION:
ebottard's answer brought me to the point of creating a "spring-shell-plugin.xml" under resources\META-INF\spring\... Although the component scan was set externally already, this seems to be necessary. The following code shows how to start it up within an Spring Boot Application where CommandLineRunner is implemented. This should bridge starting problems.
#Component
public class CLIBean implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
Bootstrap bootstrap = new Bootstrap();
bootstrap.run();
}
}

Related

Moving to the Spring Boot. Migration of logic from the old main class

I am very new to Spring Boot and development, so, I am stuck with a problem. I have an old project that needs to be migrated to Spring Boot. The original main method has super cool multi-threaded logic. In my understanding public static void main(String[] args) was entry point to the program, now after creating Spring Boot project #springbootapplication is entry point. How to access the original logic of a method? Should it somehow be transform? I spent hours looking for a suitable solution but no luck. Could you point me? Any help is appreciated :)
You have to use #SpringBootApplication, but also need to modify the main method something like:
#SpringBootApplication
public class YourMainApplicationClass {
public static void main(String[] args) {
SpringApplication.run(YourMainApplicationClass.class, args);
}
}
This will start your application.
Then move your original code of your main method to a new class, which has annotation #Component. Implement CommandLineRunner, and override the run method. So something like:
#Component
public class YourOldMainClass implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
//Your code here
}
}
When your application starts, spring will load 'near everything' with annotation into its container, so your #Component annotated class should be also loaded. The CommandLineRunner with overrode run method will auto call your method at startup.
Also, don't forget to include necessary spring boot jars next to your project, or to your build automation tool - like Maven - if you use it.

Spring Cloud Dataflow Set System Properties

I have written a custom spring cloud stream sink application that starts up when I run it as a spring boot project in eclipse. When I deploy my application I need to pass in some system proeprties. See below.
#ComponentScan
#EnableConfigurationProperties(MyProperties.class)
#SpringBootApplication
public class MyApplication {//extends SpringBootServletInitializer{
public static final String COMPONENT_NAME = "my-application";
#Autowired
private MyProperties properties;
public static void main(String[] args) {
System.setProperty("server.env", "DEVT1");
System.setProperty("some.other.var", "foo");
SpringApplication.run(MyApplication.class, args);
}
I am trying to pass these system properties into dataflow using the Deployment Properties screen, picture below. I am wondering if I pass one of these if it is working. It seems like my application starts up but is looking for the other property. When I try passing both I get this weird error saying the main class can not be found. So when I pass one my application seems to get farther. Am I close to being on the right track? Do I need to separate the arguments some way? I tried with commas but it didn't seem to make a difference.
Error when passing two arguments -
Error: Could not find or load main class
LURzZXJ2ZXIuZW52PVBEMDYsLURBbWljYV9RdWV1ZV9NYW5hZ2Vycz1HV0QwNiwtRGNmZ21nci5jbGFzcy5wYXRoPVxhbWljYS5jb20MaWxlcxtudmNvbmZpZwdwcHJlc291cmNlcw==
So the picture in my post above is actually correct for setting jvm arguments. My error stemmed from one of my jvm arguments being a file path that was not exposed through docker. Make sure use-spring-application-json is unchecked if you specify your jvm args this way. So this is valid for passing jvm arguments...
through docker /res/ maps to a folder on my c drive.

Java Spring - How to set up environment? [duplicate]

This question already has answers here:
Running code after Spring Boot starts
(18 answers)
Closed 4 years ago.
I am building an application using Java Spring where I would like to run some environment setup code before my application starts handling requests. In this particular example, I'm using PayPal Rest SDK and I would like to set up some notification webhooks for my application. For obvious reasons I don't want to have an endpoint to call to set up the webhooks after the application is started, so putting it in my controller is probably not a good idea, and I need some Spring configuration information to set it up so I can't put it in main(). I'm ok with (in fact I'd even prefer) the application crashing if the webhooks fail to be created, if that's a constraint that needs to be considered.
What's a good way to do this?
Thanks.
and I need some Spring configuration information to set it up so I can't put it in main()
The above statement is not true. You can access your Spring configuration in a main. Consider the following example.
#SpringBootApplication
public class Main {
#Autowire
private MyService service;
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(InterviewHqApplication.class, args);
ctx.getBean(Main.class).setup();
}
private void setup() {
service.doStuff();
}
}
In this example, the setup() method is called after the application context has loaded.
There are actually several ways to do what you are attempting. Spring boot also supports using ApplicationRunner and CommandLineRunner, which both call a run method after the application context has been loaded an alternative to what I have shown above. You can also listen for an ApplicationReadyEvent and you could call #PostConstruct do perform some specific configuration on a bean after it's initialized.

How do you enable AspectJ to execute advice on a joinpoint called by a method of the same class?

I'm implementing an AOP-based caching layer similar to Spring Cache, and I'm having trouble getting my advice to execute when the joinpoint is called by another method in its own class. I was initially using Spring AOP's AspectJAutoProxy, and I understand why that doesn't allow for this use case, so I tried switching to AspectJ's load-time weaver, but it doesn't appear to have done anything. Here are all the details:
Spring version: 4.5.2
AspectJ version: 1.8.9
Java agent(s) added to run command. Note that I've tried including each of the two agents separately and together, without any difference in behavior:
-javaagent:/var/app/cops/jars/aspectjweaver-1.8.9.jar -javaagent:/var/app/cops/jars/spring-instrument-4.3.0.RELEASE.jar
Application entrypoint:
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class Application implements ApplicationContextAware {
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
// Other unrelated beans
}
Advice signature:
#Around("#annotation(cacheable)")
public Object processCacheable(ProceedingJoinPoint joinPoint, Cacheable cacheable) throws Throwable
Method signature:
#Cacheable(key = "'test-key'")
public Map<String, Object> getDataFromSource()
"processCacheable" gets executed before "getDataFromSource" is called by another class, but still not if called from within the same class. Is there some configuration I'm missing in order to get LTW working correctly?
My usual disclaimer: I am not a Spring user. So I have next to zero experience with Spring configuration. But having looked at the weaving agent you put on your command line, I cannot find any AspectJ-related stuff in there. It is a really small JAR with only instrumenting classes that seem to rely on other transformers/weavers being deployed and somehow configured in your container.
I suggest you put the actual AspectJ weaving agent on your command line and see what happens. ;-)
Update: Or you if that does not help try both agents on the command line at the same time. I cannot tell you exactly what spring-instrument does, but I think it somehow integrates aspectjweaver (which does the actual aspect weaving) deeper into the Spring framework, even though AspectJ would also work without Spring even knowing of its existence.

Using Spring in a standalone application

i am looking for samples or tutorials of using Spring in a standalone (desktop/swing) application, i searched a lot but couldn't get to something useful, all the examples and tutorials are for web applications, please advise.
Create the standalone application with maven, as pointed here:
Create a standalone application with Maven
Put the applicationContext in classpath, and load it in the main class as follows:
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext.xml");
See full article here:
http://www.devdaily.com/blog/post/java/load-spring-application-context-file-java-swing-application
Here's a simple example with 2 classes. Wrote in groovy for ease of reading, but will run for you in java too with proper syntax tweaks
Here's your main:
class Main {
static void main(String[] args) {
def ctx = new AnnotationConfigApplicationContext()
ctx.register(AppConfig.class)
ctx.refresh()
def runner = ctx.getBean("mainRunner")
runner.run()
}
void run() {
println "running from bean"
}
}
Here's your config bean:
#Configuration
class AppConfig {
#Bean
Main mainRunner() {
new Main()
}
}
AppFuse provides different demo applications, all the source code can be downloaded using maven. You can get the complete code of this demo application which is build using Spring MVC,Spring, Hibernate.
Yes this is a web application, you can dig into it and convert it to a stand alone one.
create a Maven project
it will create an Application class for your project
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
//SpringApplication.run(YourClass.class, args);
YourClass.main(args);
}
}
put YourClass main method in there instead of SpringApplication.run(YourClass.class,args);
it works that way just fine.
When I first started to learn spring I followed these tutorials:
tutorialspoint
They are fairly basic but will get you up and running quickly. After this is ultimately
comes down to what you are going to use it for. Are you looking for IOC, JMS, JDBC/Hibernate support etc etc?
As mentioned already:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext");
will bring all your spring beans into your app regardless of what type it is.
This is the first thing I found on google. It looks fair good too.
http://www.mkyong.com/spring/maven-spring-hibernate-annotation-mysql-example/
Take a look at "Barebones Spring". I think it's a nice, up to date example of how to use Spring 3.
This is the tutorial of Spring which I found to be very useful. This explains Spring based on a Standalone application.
https://www.youtube.com/watch?v=GB8k2-Egfv0
Author of this videos also has updated the Maven and Struts videos and explained it in a simple but in an effective way.
I hope it helps.
I have managed to run a standalone Spring Boot application with Swing.
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(SwingApp.class)
.headless(false).run(args);
EventQueue.invokeLater(() -> {
SwingApp ex = ctx.getBean(SwingApp.class);
ex.setVisible(true);
});
}
We need to use the SpringApplicationBuilder and turn off the headless mode.
#SpringBootApplication
public class SwingApp extends JFrame {
The SwingApp is decorated with #SpringBootApplication annotation.
See my Spring Boot Swing integration tutorial for a full working example.
So, to boil it down: what makes your application (any type) a Spring application is the presence and use of at least one BeanFactory, usually extended as an ApplicationContext. In a web application you'd likely declare in web.xml a servlet such as DispatcherServlet which takes care of instantiating and initializing the context; in a standalone application your own code just makes and initializes a context, as shown above. The web framework stuff that magically gives you a context is doing pretty much the same thing under the covers.
Following 4 libraries are needed for a minimal standalone Spring application :
commons-logging.jar (see http://commons.apache.org/logging)
org.springframework.core-2.5.6.A.jar (see
http://www.springsource.org/download)
org.springframework.beans-2.5.6.A.jar (see
http://www.springsource.org/download)
org.springframework.context-2.5.6.A.jar (see
http://www.springsource.org/download)
A good example is given here.

Categories

Resources