Vaadin-SpringBootServletInitializer vs AppShellConfigurator .What is valid for production build on external Tomcat? - spring-boot

I'm building my project with Spring Boot and when uploading to Tomcat as a .war it was throwing errors.
In any case what fixed it is to change
public class Application implements AppShellConfigurator {
to
public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
I've used a sampler from start.vaadin.com v22 to build upon which came by default with the
Application implements AppShellConfigurator
Like this it was running fine inside Intellij with the embedded Tomcat but when deploying to a standalone/external one , I had to change that to the latter.
Is that required ? if yes then the docs should be updated because at
https://vaadin.com/docs/v22/flow/production/production-build
there's no mention of it.

As M. Deinum said this is related to Spring Boot.
Usually you run the Spring Boot Application as an executable JAR. But If you want to run it as a WAR inside a Tomcat you have to use SpringBootServletInitializer.
The first step in producing a deployable war file is to provide a
SpringBootServletInitializer subclass and override its configure
method. Doing so makes use of Spring Framework’s servlet 3.0 support
and lets you configure your application when it is launched by the
servlet container. Typically, you should update your application’s
main class to extend SpringBootServletInitializer...
Source: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.traditional-deployment

Related

Spring AOP aspect doesn't get applied if included from an external jar with different package name

I have a spring boot rest service that included an external project in pom as it's dependency. That external project is basically a jar that has spring AOP code.
The base package in my main application that includes this external jar with spring AOP code is x.y.z
The class in external jar where the #before advice is, is under the package a.b.c
With this class under a.b.c package, it doesn't get recognized by the main application where I want to use the spring aop implementation and apply the aspect. However, when I change it's package from a.b.c to x.y.z (which I really can't do in real life) it works fine.
I know that in spring boot service which happens to be the including service, it scans everything under root package given in the application class, x.y.z in this case and that is why aspect works fine if it's class is under x.y.z.
however, the problem is that this spring app jar will be used across multiple applications. So changing package name like this is not an option.
Is there a way to accomplish this without changing the package name of the class where spring app code is ?
Probably component scan is only activated for your application class packages by default. You can extend it to multiple packages, including the aspect package:
XML style configuration:
<context:component-scan base-package="x.y.z, a.b.c" />
Annotation style configuration:
#ComponentScan(basePackages = {"x.y.z", "a.b.c"})
Disclaimer: I am not a Spring user, only an AspectJ expert. I just knew that you can configure component scan, googled the syntax for you and hope it is correct.
Please define the bean (of jar project )inside main application. Give the #ComponentScan(basePackages = {"x.y.z", "a.b.c"}) as well as #EnableAspectJAutoProxy. Also include below piece of code.
ex:
` #Bean
public LoggingHandler loggingHandler()
{
return new LoggingHandler();
}`
Also annotate external jar code with:
`#Aspect
#Component
public class LoggingHandler {`
What #kriegaex suggests is correct. In addition to that, please make sure you are using #Component along with #Aspect. Since #Aspect is not a Spring annotation, Spring won't recognize it and hence your aspect won't be registered. So, using #Component is mandatory to getting aspects to work in Spring environment.

How to integration test auto configuration for a custom Spring Boot style starter library?

I am writing a library to provide some functionality that is shared between multiple different Spring Boot applications that I work with.
I would like to do something similar to the auto-configuration that is provided by the many Spring Boot starter libraries exist. That, or some other simple declarative way to integrate my library with the ApplicationContext of the apps using it.
I have found some resources explaining how auto configuration works. I can figure out the above problem.
However, I have not been able to find any good examples of how I can test as part of my library's test suite that it suitably integrates with a Spring Boot application. Ideally, I would start up a simple Spring Boot app written in the library's test directly just for the sake of testing, add the right annotation to it, and be able to assert that the correct beans are then configured.
I have tried creating a TestApplication class that does that and writing integration tests using the SpringBootTest annotation but the TestApplication was never started before my test started.
What can I do to start up a simple app like that solely for the purpose of testing my library? My tests are written with Spock and Spock-Spring in case that changes things versus other test frameworks.
I was able to make it work with the following test class:
#SpringBootTest
#ContextConfiguration(classes = TestApplication)
class DummyIntegrationSpec extends Specification {
#Autowired
DummyService dummyService
void 'dummy service should exist'() {
expect:
dummyService.getMessage() == DummyConfiguration.MESSAGE
}
}
and this TestApplication class at src/test/groovy/com/example/project/TestApplication.groovy
#SpringBootApplication(scanBasePackages = 'com.example.project.config')
#EnableAutoConfiguration
class TestApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication)
}
static void main(String[] args) {
SpringApplication.run(TestApplication, args)
}
}
The two key changes I had to make in order for the TestApplication to start and load the correct context when I moved my TestApplication class from src/main to src/test were:
the TestApplication class needed to be added to the ContextConfiguration annotation
the package that my library's Java config files live in needed to be added to the SpringBootApplication scanBasePackages field
The library auto-configuration does follow a similar structure to the one mentioned in the link tom provided.
Your auto-configuration should be automatically picked while your main spring application/test is starting and all beans will be registered in your context. They will be available for auto-wiring and follow your conditions and init order.
As a summary, make sure you have an auto-configuration annotated by #Configuration class with an #Import that imports your #Configuration annotated configuration classes (inside of them you define beans with methods annotated with #Bean). Also make sure you created a spring.factories file that include your auto-configuration class and that you removed the spring boot maven plugin (for the packaging to be right).
Also, make sure your auto-configuration project is NOT annotated by things like #SpringBootApplication, #EnableAutoConfiguration, #ComponentScan or other spring boot annotations that need to be only in the main spring boot projects (There should be one of them in each stack).
Please also see the article below:
Spring boot is based on a lot of pre-made auto-configuration parent projects. You should already be familiar with spring boot starter projects.
You can easily create your own starter project by doing the following easy steps:
Create some #Configuration classes to define default beans. You should use external properties as much as possible to allow customization and try to use auto-configuration helper annotations like #AutoConfigureBefore, #AutoConfigureAfter, #ConditionalOnBean, #ConditionalOnMissingBean etc. You can find more detailed information on each annotation in the official documentation Condition annotations
Place an auto-configuration file/files that aggregates all of the #Configuration classes.
Create a file named spring.factories and place it in src/main/resources/META-INF.
In spring.factories, set org.springframework.boot.autoconfigure.EnableAutoConfiguration property with comma separated values of your #Configuration classes:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
Using this method you can create your own auto-configuration classes that will be picked by spring-boot. Spring-boot automatically scan all maven/gradle dependencies for a spring.factories file, if it finds one, it adds all #Configuration classes specified in it to its auto-configuration process.
Make sure your auto-configuration starter project does not contain spring boot maven plugin because it will package the project as an executable JAR and won't be loaded by the classpath as intended - spring boot will not be able to find your spring.factories and won't load your configuration

cannot resolve reference to bean 'jmsconnectionfactory' when using spring boot + spring integration

I had a problem i'm using hornetq using spring boot and had to create a jmschannel in spring configuration using spring integration <int-jms:channel id="jmsChannel" queue-name="${spring.hornetq.embedded.queues}" connection-factory="jmsConnectionFactory">
<int-jms:interceptors><int:wire-tap channel="logger"/></int-jms:interceptors>
</int-jms:channel>
This is working fine in local when loading with undertow, when deployed the war to Jboss it is throwing up saying bean named jmsConnectionFactory not found, any help is greatly appreiciated
Looks like there is nothing to do with the Spring Integration, but only Spring Boot stuff, which is called deployable war:
The first step in producing a deployable war file is to provide a SpringBootServletInitializer subclass and override its configure method. This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure your application when it’s launched by the servlet container. Typically, you update your application’s main class to extend SpringBootServletInitializer:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}

How to migrate from traditional java web application (with web.xml) to spring boot?

I wanna switch my projects to spring-based product.
My first step is to transform my java web application from a generated WAR file, to a standalone executable jar, powered by spring boot.
Let's take a open source web application example from github.: Vaadin-Spring Web Application
The web.xml file can be found here.
The root-context file can be found here.
I hope that there are some guides for me to perform the transformation.
I have also submit an issue in the spring-boot project.
This application is not a Spring MVC application as far as I can tell - it would probably be a lot easier to migrate if it was. The goal (per the github issue) is to obtain an executable JAR. The basic plan though might be to migrate first to a WAR using Spring Boot and then to a JAR once that is working. It's a pretty simple app so all we really need to do is look at the web.xml and translate it into the relevant Spring Boot features. Here are some general guides:
Create a deployable WAR by extending SpringBootServletInitializer (e.g. in a class called Application), and add the Spring Boot #EnableAutoConfiguration annotation. Example:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
Then add some configuration:
A #Bean of type Servlet or ServletRegistrationBean installs that bean in the container as if it was a <servlet/> and <servlet-mapping/> in web.xml
A #Bean of type Filter or FilterRegistrationBean behaves similarly (like a <filter/> and <filter-mapping/>).
The ApplicationContext in this case is rooted in an XML file, so the easiest first step is to #Import that into the Spring Application. This one is so simple that it can be recreated in a few lines as #Bean definitions.
Static resources can be moved to /public (or /static or /resources or /META-INFO/resources) in the classpath root
Once the WAR is working we make it executable by adding a main method to our Application, e.g.
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
See also the Getting Started Guide on Converting a JAR to a WAR.
As I said, the biggest problem with this specific app is that it isn't a Spring MVC app. As the Irishman might say "If I wanted to get to there, sir, I wouldn't be starting from here." This is an interesting question in general, but I recommend anyone else looking to migrate a Spring application to Spring Boot read the general advice here but maybe start another discussion somewhere else.
Anyway, I'll have a bash at converting this specific app (source code jars would be nice), and update this response if I learn anything new.

How to use OSGI service inside Vaadin web application running in Jboss AS 7

I'm new to OSGI and currently trying to use it to create modular web application. Web application itself is created using Vaadin 6.
I following this WIKI article at Vaadin web site: Creating Modular Vaadin application with OSGI
Steps I've did so far:
- created OSGI bundle for module service (simple service which tracks other osgi modules a.k.a. plugins) and deployed it to jboss.
- created vaadin application, just a stub.
OSGI service supposed to be injected to Servlet class, like:
#WebServlet(urlPatterns="/*")
public static class Servlet extends AbstractApplicationServlet {
#Resource(mappedName="vaadin-moduleService")
ModuleService moduleService;
#Override
protected Class<? extends Application> getApplicationClass() {
return ModuleDemoApp.class;
}
#Override
protected Application getNewApplication(HttpServletRequest request) throws ServletException {
return new ModuleDemoApp(moduleService);
}
}
Now the question - how this service can be injected here? Currently I'm just getting NULL pointer, so DI doesn't work. From article referred above:
Note, that the servlet has a moduleService field annotated with the
#Resource annotation. One of the interesting features of GlassFish 3
is that it is possible to inject references to OSGi services into all
container managed Java beans, even though they are not actually
running in the OSGi container themselves. Thus, in this case, GlassFish
will find the module service we define in the previous section and inject it.
According to this Glassfish will do all the magic internally and automatically. Anyone aware of how to get it done using JBoss7?
Unfortunately didn't find any good (for newbie) explanation on how anything running inside of OSGI container can be referenced outside of it... Suppose that converting of the web application itself to OSGI bundle is not required to acomplish what I need. Is this true?
Thanks a lot.
The documentation states that the JavaEE component can get the BundleContext injected as a #Resource. If that works, then you can track your module service through a ServiceTracker.
I saw another example of using Vaadin together with OSGi here.

Resources