Merging properties files using cucumber-spring - java

We are using cucumber + selenium to facilitate e2e tests. We are using following dependencies to leverage on spring dependency injection.
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
<scope>provided</scope>
</dependency>
Then we configure spring context using these two classes
#ContextConfiguration(classes = SpringContextConfig.class)
#CucumberContextConfiguration
public class CucumberSpringConfiguration {
}
#PropertySource("application.properties")
#ComponentScan("com.example.e2e")
public class SpringContextConfig {
}
As we can se we properties source is defined explicitly pointing to a given file. Is there a way to achieve the "magic" that Spring Boot does with profiles and properties files?
For example I would expect spring when specifying -Dspring.profiles.active=dev to merge
application-dev.properties with application.properties and giving the final context properties.

As we can se we properties source is defined explicitly pointing to a given file. Is there a way to achieve the "magic" that Spring Boot does with profiles and properties files?
Profile specific configuration files are a Spring Boot feature. So if you are using Spring boot, this should be sufficient to have the active profile picked up:
#SpringBootTest
#CucumberContextConfiguration
public class CucumberSpringConfiguration {
}
From your dependencies however it doesn't look like you are using Spring Boot. There is no other (easy) way to use profile specific configurations files. Consider making your application a Spring Boot application.

Related

Spring boot enable/disable tomcat or kafka consumer based on the profile

I'm writing a Spring Boot application with several #Configuration classes for rest APIs and for Kafka consumers/producers depending on which #Profile it chooses to initialize.
The first configuration class uses the REST interface, and I have these dependencies added.
This starts up an embedded Tomcat instance and runs fine.
Here the problem is the other profiles should not spin a tomcat server, it should act only as a Kafka consumer.
Is there any way to stop spinning the #SpringBootApplication from starting up Tomcat based on profiles?
I created 2 configuration classes, one for Kafka and one for rest endpoints, and added #Profile annotation for each config class. Can someone guide me on how to stop spin tomcat from my app?
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Main application:
#SpringBootApplication
#Import(value = {RestScanConfiguration.class, KafkaScanConfiguration.class})
public class MainApp {
public static void main(final String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
RestScanConfiguration class:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = "package.app.rest")
#Profile("!kafka")
public class RestScanConfiguration {
}
KafkaScanConfiguration class:
#Configuration
#EnableAutoConfiguration(
exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class
})
#ComponentScan(basePackages = {"package.app.kafka"})
#Profile("kafka")
public class KafkaScanConfiguration {
}
can someone guide me on this?
How to stop spinning the tomcat server in Kafka consumer/producer profile. Any help would be appreciated.
First you have to disbale the auto configuration for the embeded tomcat in the starter class to avoid deploying the tomcat:
#SpringBootApplication(exclude = {EmbeddedServletContainerAutoConfiguration.class,
WebMvcAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and then add the following property to your kafka config (non-Rest profiles):
spring.main.web-environment=false
now you have disabled auto-deployment of the integrated tomcat in spring boot. Now add the following configuration to your Rest profile to enable tomcat (only for this profile):
#Profile({"REST"})
#Configuration
// importing EmbeddedServletContainerAutoConfiguration delays the autoconfiguration until the profile load into context
#Import(EmbeddedServletContainerAutoConfiguration.class)
public class HttpConfiguration {
// ...
}
and afterwards you have configure your kafka dynamically. You can find a solution for that in Control enabling/disabling Kafka consumers in Spring Boot
Instead of configuring this in code I'd suggest you to create application-kafka.properties (or application-kafka.yml) and add the following line into it:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
This disables ServletWebServerFactoryAutoConfiguration which is a root configuration class for Web environment.
-kafka suffix in properties file name tells Spring to pick it up only when kafka profile is active.
Even better solution is to exclude
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
from built jar. In other words you could have a pom.xml two profiles with only required dependencies (shared ones are located in main dependencies section). See https://stackoverflow.com/a/167284/12473843. Using this approach you don't even need specifying excluded autoconfigurations as without spring-boot-starter-web in the classpath corresponding started is never activated.

Migrate java web app to spring boot?

I am considering modifying an existing java web app (with web.xml and applicationContext.xml files and Spring 2.5) to use Spring Boot. What are the implications of this process? I know I will need to create an #Configuration file to declare all of the beans (to eliminate the applicationContext.xml files), but would love some additional insight. Any suggestions are appreciated!
Migration would take several steps. Some of them are:-
Add Spring Boot dependencies to your pom.xml or gradle file.
Define all the XML beans using Java Configuration by #Bean
Define Spring Security if used through Java Configuration
Add application.properties to resources directory and defines all the configuration values like database host,username,password etc
Define your views inside resources/templates
You've to include all the dependencies required. Some of the dependencies are:-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
You could have some other dependencies too like Spring Security. If your application uses Spring Security you have to provide java configuration for it.
http://www.baeldung.com/spring-boot-security-autoconfiguration
https://spring.io/blog/2014/01/30/migrating-from-spring-framework-3-2-to-4-0-1

Spring boot - Unable to resolve jsp views

I am trying to build a basic MVC app using Spring boot with Hibernate as ORM and MySql as Database. The problem that I am facing is that the jsp views are not getting resolved.
I get a 404 error when I try to fetch the registration form using a GET request with the following URL:
http://localhost:9000/users/register/
This is the set-up that I have in my application.
Directory structure:
-src
-main
-java
-com
ApplicationStart.java
-controllers
UserController.java
-repositories
UserRepository.java
-webapp
-WEB-INF
-jsp
register.jsp
-resources
application.properties
UserController:
#RestController
public class UserController {
private UserRepository userRepository;
#Autowired
public UserController(UserRepository userRepository)
{
this.userRepository = userRepository;
}
#RequestMapping(value = "/users/register", method = RequestMethod.GET)
public String Register()
{
return "register";
}
}
Application.properties:
server.port: 9000
spring.datasource.url: jdbc:mysql://localhost/Contacts
spring.datasource.driverClassName: com.mysql.jdbc.Driver
spring.datasource.username: root
spring.datasource.password:
spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- HIBERNATE -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<!-- MYSQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
MAIN CLASS
#ComponentScan
#Configuration
#EnableAutoConfiguration
public class ApplicationStart {
public static void main(String[] args)
{
SpringApplication.run(ApplicationStart.class, args);
}
}
This is the current setup of my application. Any help on how to resolve the issue is much appreciated.
Please comment if more information is required.
Thanks-
Spring Boot has limited support for JSP, because of its use of an embedded servlet container. From the Spring Boot reference documentation:
When running a Spring Boot application that uses an embedded servlet container (and is packaged as an executable archive), there are some limitations in the JSP support.
With Tomcat it should work if you use war packaging, i.e. an executable war will work, and will also be deployable to a standard container (not limited to, but including Tomcat). An executable jar will not work because of a hard coded file pattern in Tomcat.
Jetty does not currently work as an embedded container with JSPs.
There is a JSP sample so you can see how to set things up.
Start by making your app an executable war, and make sure that you use Tomcat (check the log when you start the application). Unless you explicitly have stated you Jetty should be included, you are using Tomcat since that is provided by default. Alternatively, try change your view technology, which probably requires more initial work, but can significantly reduce the turnaround time during development, see Hotswapping.
I ran into this problem recently while upgrading an old project that needed to have jsps as the view technology with tomcat as an embedded servlet-container. Caveat: Pick an alternative templating engine, and avoid jsps if you can. But if you can't avoid jsps, and your application is not able to resolve them, at the time of this writing (spring-boot 2.x.x), ensure the following:
Ensure that application packaged as a war and not a jar. Although it is not impossible to get jsps to work with a jar packaging, it is a little complicated due to certain limitations. You could just run them with a war package in a server or container just fine like: java -jar war-filename.war
Verify that your controllers have the #Controller annotation
BUT NOT the annnotation #EnableWebMvc. That's because you are using spring-boot to configure WebMVC for you.
Is your controller being scanned and injected as a component? If you have defined your controllers in a different package, maybe you are missing a #ComponentScan annotation?
Are you jsps located and configured correctly? For example, let's say your jsps are located in /src/main/webapp/WEB-INF/jsp/, then your application.properties should have something like so:
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
Also, since you are using spring-boot, there is no need for your Application to extend the SpringBootServletInitializer. It will work too, but to keep it simple, all you need is a class like below:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
FYI, the minimal set of dependencies needed are mentioned below (Maven Example):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<dependencies>
<!-- spring-boot dependencies below -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- jstl and jsp compilation support below -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
Agree with #code4kix, If all of this doesn't work, try adding below property in your application.properties file
spring.thymeleaf.enabled=false
In my case that solved my problem
Location of JSP file: src/main/resources -> /META-INF/resources/WEB-INF/jsp/sayHello.jsp
In pom.xml :
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
In application.properties:
spring.mvc.view.prefix= /WEB-INF/jsp/
spring.mvc.view.suffix= .jsp
#For debug reason
logging.level.org.springframework=debug
In Contoller:
#Controller
public class HelloController {
#RequestMapping("say-hello-jsp")
public String sayHelloJsp() {
return "sayHello";
}
}
Intellij still show it as error, but it works
In IntelliJ, if you have the same configurations and it still doesn't work do this:
File -> Invalidate Caches -> mark first 2 lines -> Invalidate and Restart. Then it will work fine

Some doubts about Spring AOP example

I am leargnin AOP in Spring Framework studying on this tutorial: http://www.tutorialspoint.com/spring/schema_based_aop_appoach.htm
Differently from the previous tutorial I am not adding manually the needed jars file but I am using Maven.
Initially I have added this dependencies in my pom.xml (in addition to those relating spring-core, spring-bean, spring-context, spring-context-support Spring modules)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
But, in this way don't work and raises me the following exception:
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException
Reading online I have found the solution: I have to add these two dependencies in my pom.xml:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
So now I have two doubt:
Why I have to add this org.aspectj.aspectjtools dependencies if I have yet org.springframework.spring-aop? (Also...I noticed that I could delete the org.springframework.spring-aop, this is not used)
What is the difference between them?
Why I have to add cglib dependecies?
I know that I have to use cglib when I use annotations like #Configuration and #Bean...but why I need this dependencies in this case that have not these annotation?
Tnx
Andrea
You could have used aopalliance instead of cglib, and aspectjrt & aspectjweaver dependencies in your pom.xml. What I use and suggest is compile team weaving of your target code using Maven aspectj-maven-plugin.
As to your questions, Spring AOP does not itself instrument your target code. It uses AspectJ behind the scenes to do that. CGLib is used to generate Dynamic Proxies etc. If you need to dynamically generate an interface and then apply it to your advices then, CGLib can assist. Hibernate heavily uses CGLib

NetBeans: add Spring IOC to maven based Swing Application Framework project

I want to add spring IOC to maven based Swing Application Framework project. So I added to pom.xml dependencies:
<!-- Spring IOC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.0.RELEASE</version>
<scope>runtime</scope>
</dependency>
<!-- log4j for Spring -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>runtime</scope>
</dependency>
And initializated ApplicationContext in main():
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.mypackagewithbeans");
ctx.refresh();
launch(DesktopApplication1.class, args);
}
But I can't build project, because IDE can not see spring libraries at all. I tried to remove <scope>runtime</scope> line, but it does not fix the problem (IDE can not see annotations, for example, #Autowire).
What should I do to add the Spring IOC support to the NetBeans Swing Application Framework project (using maven)?
make sure that you've created a new Maven project in NetBeans and not just a 'Java Desktop Project' (these don't recognize the pom.xml). make sure to select the 'Swing Application Framework project' maven archetype when the wizard asks you to select an archetype.
to check, does your project icon have a small 'M' at the top left corner (indicating it's a maven project)

Categories

Resources