I made up an example spring boot project running with Vaadin (latest version). I only have one view:
#Route
public class MainView extends VerticalLayout {
The UI was working like a charm, then I had to refactor the project in modules.
I put the SpringBootApplication in a module and Vaadin in another one. I'm getting into modules, so I don't know exactly how they interact, but I had to put the dependency in the boot pom to the vaadin pom in order to let it start.
Now it is not working, when I call localhost it says
Could not navigate to ''
Reason: Couldn't find route for ''
Available routes:
This detailed message is only shown when running in
development mode.
The spring boot application:
#SpringBootApplication
#ComponentScan(basePackages = {"my.app"})
#EntityScan(basePackages = {"my.app"})
#EnableJpaRepositories(basePackages = {"my.app"})
#EnableJpaAuditing
public class LicensemanagerApplication
boot module pom.xml dependency snippet:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>app_frontend</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
app_frontend module pom.xml dependency snippet:
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
.............
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>13.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Vaadin by default only looks for #Route annotated classes within the same package that contains the #SpringBootApplication annotation. To make it look in other packages, you need to pass those as the value to the #EnableVaadin annotation, e.g. #EnableVaadin({"my.app"}).
Related
Im having a Springboot project where I have found a way to create and run simple Junit testcase which looks into a repository and fetches some data attribute for a given entity. The result of the Junit run is pass so no problem in regards to that.
But the thing is here, that I have seen a lot of examples out there where tutorials are showing Springboot projects where they can simply run Junit tests with only #Runwith or #SpringBootTest
for their specific test classes.
In my case I have to add 3 annotations, #SpringBootTest, #RunWith as well as #ContextConfiguation(with parameters) until Im able to run the testcase.
So my question is how will I be able to run it as minimalistic as possible, (some exercises I have seen have only one annotation for their springboot test class)
My Springboot test class looks like this:
Screenshot of my Junit class
and my Directory structure looks like this:
Screenshot of my Project directory structure
My application.properties looks like this:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/erfan
spring.datasource.username=erfan
spring.datasource.password=
#Some additional properties is trying to be set by Spring framework so this must be set
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
#spring.datasource.initialization-mode=always
#spring.datasource.initialize=true
#spring.datasource.schema=classpath:/schema.sql
#spring.datasource.continue-on-error=true
#HikariCP is a ConnectionPool manager, related to DB stuff
#Below is the property key you need to set to * as value to expose all kind of monitoring related information
#about your web application
#management.endpoints.web.exposure.include=*
And my pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<groupId>com.sample</groupId>
<artifactId>postgres</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>postgres</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
So am I missing like something in my application.properties file? Something that I should include to be able to remove "boilerplate" annotation in my test class?
Depends on what you're trying to do. Basically spring has custom annotations that configures the spring context to include only relevant beans. This is the so called test slices.
But there are a few "rules" I always try to follow:
Avoid #SpringBootTest unless you're doing integration testing, or manually setting which classes to use #SpringBootTest(classes = {MyService1.class, MyService2.class}
If you're testing spring jpa, you can use the #DataJpaTest annotation, example here
If you're testing controllers you can use the #WebMvcTest, example here
If you're testing other services, you can always use #ContextConfiguration to configure the spring context accordingly.
So for example, for your test I would write it in one of two ways:
#RunWith(SpringRunner.class)
#DataJpaTest
#Import(AnotherConfig.class)
class MyTest {
// test stuff here
}
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {AnotherConfig.class})
// NOTE, if you have a JpaConfig class where you #EnableJpaRepositories
// you can instead add this config class to the #ContextConfiguration classes
#EnableJpaRepositories
class MyTest {
// test stuff here
}
Basically, don't worry about how many annotations you have on top of your test, but worry about which beans/services are being autowired. For example the #SpringBootTest is a single annotation, but autowires all the beans in the spring context.
I strongly recommend not using a bunch of spring annotations on unit tests. Unit tests should only test one piece of code and not relate with externals or other layers, so Mockito should be sufficient.
Example:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#InjectMocks
private FooService service;
#Mock
private FooRepository repository;
#Test
public void whenHappyPath_shouldReturnTrue(){
doReturn(Optional.empty()).when(repository).findById(anyLong());
assertTrue(service.isFoo(1L));
}
}
You are preventing your unit test to reach the repository layer, so you don't need to create a context with embedded DB or any other thing.
If you are using for integration tests then it is different and you will need different strategies. For that, I'd recommend use embedded DB on tests (which is made by default if you have h2 dependency):
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
And also use a integration or test spring profile:
#ActiveProfile("test") // or integration, you choose
public class FooIntegrationTest{
...
}
or force other configuration file to point to another configuration
#TestPropertySource(properties = { "spring.config.location=classpath:application-test.yml" })
application-test.properties
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
Erfan, it completely depends on your test scenario.
First Scenario : Complete test (Integration Test)
If you want to test the whole of your app, like testing the Service layer, Repository layer, and the Controller layer, you need a real spring-context, so you must use all #SpringBootTest and #RunWith and ... to initialize spring context to test whole layers.
(This called integration-test)
Unit Test vs Integration Test: What's the Difference
how-to-use-java-integration-testing
Second Scenario: Unit test
If you want just to test a piece of your code, just like you want to test just service layer and other layers (like repository) does not important in your scenario, in this situation you must use some new framework like Mockito, to mock the pieces that you don't want to test them, in these scenarios you don't need the **spring-context initialization ** so you don't need to use #SpringBootTest or other annotations.
Mockito Sample
So based on your scenario you can use those annotations.
I strongly recommend you to read the below link for further information about best practices for testing in java.
Modern Best Practices for Testing in Java
Starting with Spring Boot 2.0.2-RELEASE actuator 'metrics' endpoint isn't available even using following configuration:
management:
endpoints.web.exposure.include: "*"
The same configuration exposes metrics endpoint with Spring Boot 2.0.0-RELEASE
pom.xml:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
...
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
....
Any ideas how to resolve this issue?
Finally I found that there is an instance of org.springframework.boot.actuate.metrics.MetricsEndpoint should exist in Spring context in order to let Actuator show '/metrics' endpoint.
org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration
is responsible to create an instance of MetricsEndpoint but for some reason it never creates it.
So, I've created this bean in my own configuration:
#Bean
public MetricsEndpoint metricsEndpoint(MeterRegistry registry) {
return new MetricsEndpoint(registry);
}
It's fixed the problem but I'm not sure this this the best solution.
I made a similar sample . My application.yml is like this.
I like to know if below is possible and how.
I was following a tutorial for spring boot and it was mentioned there we can have a parent dependency.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
And then define the dependencies without the version number.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
This will add the dependencies version 1.5.6.RELEASE of spring-boot-starter and spring-boot-starter-web in to the projects dependencies.
Just like that I want to find what is the <parent> code snippet for the following dependencies I need to add in to a new project.
Dependencies in <groupId>org.springframework</groupId>. I need to use the version 4.3.9.RELEASE.
spring-context
spring-jdbc
spring-test
Thanks!
If you are using Spring Boot then these three dependencies will be provided for you by the following starters:
spring-test will be provided by spring-boot-starter-test
spring-context will be provided by spring-boot-starter-data-jpa
spring-jdbc will be provided by spring-boot-starter-jdbc
So, with the following parent:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
... if you add these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
... then you will get
spring-context
spring-jdbc
spring-test
However, Spring Boot 1.5.6.RELEASE depends on v4.3.10.RELEASE of those core Spring libraries not 4.3.9.RELEASE as suggested in your question. Typically, you would accept Spring's curation of dependencies so if Sping provides 4.3.10.RELEASE then either (a) you should use that version or (b) downgrade Spring Boot toa version which provides 4.3.9.RELEASE.
Read on for details on how to identify the correct starter for a given curated library ...
The spring-boot-starter-parent is a special starter that provides useful Maven defaults and a dependency-management section which defines numerous dependencies which you might want to use in your POM. These dependencies are often referred to as "curated" or "blessed" and since they are defined in a dependency-management section somewhere in the maven hierarchy you can refer to them in your POM without a version tag (i.e. they inherit the version from the dependency-management section entry.)
You can see the spring-boot-starter-parent POM here and peeking inside you can see that it references the spring-boot-dependencies POM here.
Looking at your question you mentioned that you can declare a dependency like so ...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
... this is because the spring-boot-dependencies POM declares the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${revision}</version>
</dependency>
So, the parent and the starters are just a means of wrapping up dependency declarations and making them easier for application developers to use. The Spring docs summarise this as:
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.
However, this does not mean that all dependencies must be declared via parents or starters so, if you are not using Spring Boot then you can declare a dependency without using a parent or a starter and what you have described in your question (declaring dependencies on 3 core Spring libraries) can be safely covered by simply depending on those 3 libraries explicitly. For example, just add the following to your your pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.9.RELEASE</version>
<scope>test</scope>
</dependency>
Since you are going though the tutorials I'm assuming you are new to spring.
The folks at spring were nice enough to setup a site that generates projects.
It is very easy to use. I recommend trying that while learning. Download a few apps with the dependencies you want and look at how they are set up.
Once you are comfortable and want to dive deeper, read #glytching's answer again, it is very good.
Use spring-framework-bom if you don't use Spring Boot and need Spring Framework dependencies only:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
In such case dependency would be without version was specified:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
Also, yet another option exists if you use Spring Boot but you don't want to use spring-boot-starter-parent as parent artifact:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
See Spring Boot docs for more details. An important note from the docs:
Each release of Spring Boot is associated with a base version of the Spring Framework so we highly recommend you to not specify its version on your own.
It means that you should use Spring Framework version is defined for Spring Boot.
I was trying to deploy my own custom sink of spring cloud data flow onto cloud foundry.
My Dependency are below :
<dependencies>
<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>spring-cloud-starter-stream-sink-log</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
<version>1.2.0.RC1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>app-starters-core-dependencies</artifactId>
<version>1.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>log-app-dependencies</artifactId>
<version>1.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
And the custom code is very basic as below :
#EnableBinding(Sink.class)
public class SinkConfiguration {
private static final Log logger = LogFactory.getLog(SinkConfiguration.class);
#ServiceActivator(inputChannel=Sink.INPUT)
public void loggerSink(String payload) {
logger.info("Hello, Rahul. The time is: " + payload);
}
}
All I see when i deploy this application is that the Error channel subscriber is created , but no Input subscriber was created. Due to this no messages are being received on to this app. Source for this app is a custom source with rest controller. The default out of box streamer app -- LogSink works successfully. But i need to create a customsink to build things on top. Do anyone see an issue what I am missing here?
If your goal is to create an entirely new custom sink, you would develop that as a standalone application by following the Spring Initializr procedure. It is simple this way and you don't need to use the existing log-sink starter in this case.
If you are trying to patch any of the OOTB application; in this case, the log-sink, then follow the patching procedure. Pay attention to importing the configuration class. Unless you do that, the associated app-starter's behavior won't kick in.
Also, it seems you're using an old release for rabbit-binder. It is better to rely on the Spring Initializr generated artifact as opposed to handcrafting dependency versions.
I would like to create two modules (dao and api) under this parent project. Module api would be restful api using Spring Boot. Since spring boot projects all have spring-boot-starter-parent as the parent module, how do I make it a child module under another parent? My understanding is Java projects can only have one parent.
You can use DependencyManagement instead of parent
Not everyone likes inheriting from the spring-boot-starter-parent POM. You may have your own corporate standard parent that you need to use, or you may just prefer to explicitly declare all your Maven configuration
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Source: Spring Boot Documentation