Springboot mail - spring-boot

This is the first time I'm trying to send mail, using spring-boot-starter-mail.I dont get any error but while sending my mail but i could not see any mail to my TO id.
application.properties
spring.mail.host = smtp.mandrillapp.com
spring.mai.username = lending#vit.in
spring.mail.password = ********
spring.mail.properties.mail.smtp.auth = true
spring.mail.properties.mail.smtp.starttls.enable = true
spring.mail.properties.mail.smtp.socketFactory.fallback = false
My Application Class
#SpringBootApplication
#ComponentScan(basePackages = {"com.mail"})
public class MailServiceApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MailServiceApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MailServiceApplication.class, args);
}
#Bean
public ServletRegistrationBean jerseyServlet(){
ServletRegistrationBean register = new ServletRegistrationBean(new ServletContainer(),"/*");
register.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyInitialization.class.getName());
return register;
}
}
JerseyInitialization.class
#Component
public class JerseyInitialization extends ResourceConfig{
public JerseyInitialization(){
super();
this.packages("com.mail.interfaces");
System.out.println("111");
//register(GenericFilter.class);
// property(ServerProperties.MONITORING_STATISTICS_ENABLED, true);
}
}
Controller Class:
#RestController
#Path("/mail")
public class MailResource {
#Autowired
MailSendInter mailInter;
#GET
#Path("/send")
public String sendMail(){
System.out.println("inside the resource Class");
boolean result = mailInter.send("aravind11081990#gmail.com", "Welcome Mail","Wlcome to the lending system");
if(result){
return "ok";
}else{
return "failure";
}
}
}
Interface Class:
#Service
public interface MailSendInter {
public boolean send(String to, String subject, String body);
}
ImplementationClass:
#Component
public class MailSendImplementation implements MailSendInter{
#Autowired
private JavaMailSender javaMailSender;
#Override
public boolean send(String to, String subject, String body) {
// TODO Auto-generated method stub
boolean result = false;
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try{
MimeMessageHelper helper ;
helper = new MimeMessageHelper(mimeMessage, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(body, true);
javaMailSender.send(mimeMessage);
result = true;
}catch(MessagingException mex){
result = false;
System.err.println("Expection"+mex);
}
return result;
}
}
Pom.Xml
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mail</groupId>
<artifactId>MailService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MailService</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm using Mandrill for sending mail
URL:https://www.mandrill.com
Username : lending#vit.in
Password: ********
Host : smtp.mandrillapp.com
Port : 587
SMTP Username : lending#vit.in
SMTP Password : ********
Can some one help to figure out the error

Related

Duplicate Key Error on saving Reactor Mongo result

I'm seeing the following error when attempting to query and update some records to MongoDB using reactive streams:
org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }; nested exception is com.mongodb.MongoWriteException
I'm not sure what I'm doing wrong; How do I go about querying and saving results to the database using reactive mongo in a single transaction?
My service class:
package com.example.reactivemongotransaction.service;
import com.example.reactivemongotransaction.dto.Submission;
import com.example.reactivemongotransaction.repository.SubmissionRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#Slf4j
#Service
public class SubmissionService {
#Autowired
private SubmissionRepository submissionRepository;
public Mono<Submission> saveSubmission(Submission submission) {
log.debug("saving {}", submission);
return submissionRepository.save(submission);
}
#Transactional
public Flux<Submission> lockSubmissions() {
log.debug("setting all locked");
Flux<Submission> submissionFlux = submissionRepository.findAllByLockedFalse();
return submissionFlux
.map(submission -> submission.setLocked(true))
.flatMap(submission -> submissionRepository.save(submission));
}
}
My config:
#Configuration
#EnableMongoAuditing
#EnableTransactionManagement
public class MongoConfiguration {
#Bean
public ReactiveTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
}
Controller:
#RestController
#RequestMapping("/submissions")
public class SubmissionController {
#Autowired
private SubmissionService submissionService;
#PostMapping
public Mono<Submission> saveSubmission(final #RequestBody Submission submission) {
return submissionService.saveSubmission(submission);
}
#GetMapping("/lockall")
public Flux<Submission> lockAll() {
return submissionService.lockSubmissions();
}
}
Model:
#ToString
#Getter
#Setter
#Accessors(chain = true)
#Document(collection = "submission")
#TypeAlias("payload")
public class Submission implements Persistable<String> {
#Id
private String id;
#Field("role_name")
#Indexed(unique = true)
private String role;
#CreatedDate
private ZonedDateTime created;
#LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
private boolean locked;
#Override
#JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
Repository:
public interface SubmissionRepository extends ReactiveMongoRepository<Submission, String> {
Flux<Submission> findAllByLockedFalse();
}
Main class:
#EnableReactiveMongoRepositories
#SpringBootApplication
public class ReactivemongotransactionApplication {
public static void main(String[] args) {
SpringApplication.run(ReactivemongotransactionApplication.class, args);
}
}
application.yml:
spring:
data:
mongodb:
uri: 'mongodb://localhost:27017/testtrans'
server:
port: 8280
Maven pom:
<?xml version="1.0" encoding="UTF-8"?>
<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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>reactivemongotransaction</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>reactivemongotransaction</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<lombok.version>1.18.6</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My request is GET http://localhost:8280/submissions/lockall which return 500. And the logs show errors e.g.:
com.mongodb.MongoWriteException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }
at com.mongodb.internal.async.client.AsyncMongoCollectionImpl.lambda$executeSingleWriteRequest$9(AsyncMongoCollectionImpl.java:1075) ~[mongodb-driver-core-4.1.1.jar:na]
The issue was related to the #CreatedDate not being set (see #EnableMongoAuditing and #CreatedDate Auditing not working in Spring Boot 2.4.3).
Resolved by reverting spring-boot-starter-parent to 2.3.5.RELEASE.

created repository method is returning wrong output like packagename.classname.table (com.blogconduitapi.entity.Users#6a3258a4)

I am new lerner of spring boot, i am creating a project after inserting user data into database when i am fetching data from table using method "User findByEmail(String email) it should return user object but it returning something like "com.blogconduitapi.entity.Users#5e2f219c".
All the codes are mentioned below
this is entity class
package com.blogconduitapi.entity;
import javax.persistence.*;
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue
private int id;
private String name;
private String email;
private String password;
private boolean isEnabled;
public Users() {
}
public Users(String name, String email, String password, boolean isEnabled) {
this.name = name;
this.email = email;
this.password = password;
this.isEnabled = isEnabled;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
}
this is controller
package com.blogconduitapi.controller;
import com.blogconduitapi.entity.Users;
import com.blogconduitapi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class UserController {
#Autowired
UserService userService;
#PostMapping(value = "/register")
public String registerUser(#RequestBody Users users) {
Users existingUsers1 = userService.findUser(users.getEmail());
users.setEnabled(true);
userService.createUser(users);
return "user save successfully";
}
}
this is UserService
package com.blogconduitapi.service;
import com.blogconduitapi.entity.Users;
public interface UserService {
Users findUser(String email);
void createUser(Users users);
}
this is repository
package com.blogconduitapi.repository;
import com.blogconduitapi.entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends JpaRepository<Users, Integer> {
Users findByEmail(String email);
}
5.this is serviceImpl
package com.blogconduitapi.service.impl;
import com.blogconduitapi.entity.Users;
import com.blogconduitapi.exception.UserDefinedException;
import com.blogconduitapi.repository.UserRepository;
import com.blogconduitapi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class UserServiceImpl implements UserService {
#Autowired
UserRepository userRepository;
#Override
public Users findUser(String email) {
Users users = userRepository.findByEmail(email);
System.out.println("{{{{{{{{{}}}}}}}}}}} " + users);
if (users != null) throw new UserDefinedException("mail already exist");
return users;
}
#Override
public void createUser(Users users) {
if (users.getName().isEmpty() || users.getEmail().isEmpty() || users.getPassword().isEmpty()) {
throw new UserDefinedException("There are some required fields are missing");
}
userRepository.save(users);
}
}
application.property
spring.datasource.url= jdbc:postgresql://localhost:5432/apidb
spring.datasource.username=postgres
spring.datasource.password=admin
spring.jpa.hibernate.ddl-auto=update
7.this is pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>blogconduitapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>blogconduitapi</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jdbc -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The method is working it's just the issue with print. Override toString() method in your User class and try printing the user again. Java has no idea how to convert your User to string and print it in format you would like otherwise.

javax.servlet.ServletException: Circular view path [products]

I am new in Java Spring 4.0. Here is my project set up.
ProductController
#Controller
public class ProductController {
private ProductService productService;
#Autowired
public void setProductService(ProductService productService) {
this.productService = productService;
}
#RequestMapping("/products")
public String listProducts(Model model){
model.addAttribute("products",productService.listAllProducts());
return "products";
}
#RequestMapping("product/{id}")
public String getProduct(#PathVariable Integer id, Model model){
model.addAttribute("product", productService.getProductById(id));
return "product";
}
#RequestMapping("product/edit/{id}")
public String edit(#PathVariable Integer id, Model model){
model.addAttribute("product",productService.getProductById(id));
return "productform";
}
#RequestMapping("/product/new")
public String newProduct(Model model){
model.addAttribute("product",new Product());
return "productform";
}
#RequestMapping(value = "/product", method = RequestMethod.POST)
public String saveOrUpdateProduct(Product product){
Product saveProduct = productService.saveOrUpdateProduct(product);
return "redirect:/product/" + saveProduct.getId();
}
#RequestMapping("/product/delete/{id}")
public String delete(#PathVariable Integer id){
productService.deleteProduct(id);
return "redirect:/products";
}
}
ProductServiceImpl
#Service
public class ProductServiceImpl implements ProductService {
Map<Integer, Product> products;
public ProductServiceImpl(){
loadProducts();
}
#Override
public List<Product> listAllProducts() {
return new ArrayList<>(products.values());
}
#Override
public Product getProductById(Integer id) {
return products.get(id);
}
#Override
public Product saveOrUpdateProduct(Product product) {
if (product != null){
if (product.getId() == null){
product.setId(getNextKey());
}
products.put(product.getId(), product);
return product;
} else {
throw new RuntimeException("Product Can't be nill");
}
}
#Override
public void deleteProduct(Integer id) {
products.remove(id);
}
private Integer getNextKey(){
return Collections.max(products.keySet()) + 1;
}
private void loadProducts(){
products = new HashMap<>();
Product product1 = new Product();
product1.setId(1);
product1.setDescription("Product 1");
product1.setPrice(new BigDecimal("12.99"));
product1.setImageUrl("http://example.com/product1");
products.put(1,product1);
Product product2 = new Product();
product2.setId(2);
product2.setDescription("Product 2");
product2.setPrice(new BigDecimal("14.99"));
product2.setImageUrl("http://example.com/product2");
products.put(2, product2);
Product product3 = new Product();
product3.setId(3);
product3.setDescription("Product 3");
product3.setPrice(new BigDecimal("34.99"));
product3.setImageUrl("http://example.com/product3");
products.put(3, product3);
Product product4 = new Product();
product4.setId(4);
product4.setDescription("Product 4");
product4.setPrice(new BigDecimal("44.99"));
product4.setImageUrl("http://example.com/product4");
products.put(4, product4);
Product product5 = new Product();
product5.setId(5);
product5.setDescription("Product 5");
product5.setPrice(new BigDecimal("25.99"));
product5.setImageUrl("http://example.com/product5");
products.put(5, product5);
}
}
So, I am injecting a CRUD service to the controller and works good. I can post, delete, display and update data. Now I want to make mockito test. So.
ProductControllerTest
public class ProductControllerTest {
#Mock
private ProductService productService;
#InjectMocks
private ProductController productController;
private MockMvc mockMvc;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(productController).build();
}
#Test
public void testList() throws Exception{
List<Product> products = new ArrayList<>();
products.add(new Product());
products.add(new Product());
when(productService.listAllProducts()).thenReturn((List)products);
mockMvc.perform(get("/products"))
.andExpect(status().isOk())
.andExpect(view().name("products"))
.andExpect(model().attribute("products",hasSize(2)));
}
}
Unfortunately, the test doesn't pass.
javax.servlet.ServletException: Circular view path [products]: would
dispatch back to the current handler URL [/products] again. Check your
ViewResolver setup! (Hint: This may be the result of an unspecified
view, due to default view name generation.)
Why is this happening? I mean I can display the products in my browswer, but the unit test fails.
I am using spring boot and the thymeleaf template.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>theo.tziomakas</groupId>
<artifactId>springmvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springmvc</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Please try to add #ResponseBody annotation on methods of ProductController with #RequestMapping as shown below.
#RequestMapping("/products")
#ResponseBody
public String listProducts(Model model){
model.addAttribute("products",productService.listAllProducts());
return "products";
}
Hope it would help.

Spring REST Controller Not Starting

pom.xml
<groupId>com.ibm.springboot</groupId>
<artifactId>spring-boot-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-api</name>
<description>Spring API DATA</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
SpringBootApiApplication.java
#SpringBootApplication
#ComponentScan("com.ibm.springboot.*")
#EntityScan("com.ibm.springboot.topics.Topic")
#EnableJpaRepositories("com.ibm.springboot.topics.TopicRepository")
public class SpringBootApiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApiApplication.class, args);
}
}
Topic.java
#Entity
public class Topic {
#Id
private String id;
private String name;
private String description;
public Topic(String id, String name, String description) {
super();
this.id = id;
this.name = name;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
TopicController.java
#RestController
public class TopicController {
#Autowired
TopicService topicService;
#RequestMapping("/topics")
public List<Topic> getAllTopics(){
return topicService.getAllTopics();
}
#RequestMapping(method=RequestMethod.POST,value="/topics")
public void addTopic(#RequestBody Topic topic){
topicService.addTopic(topic);
}
}
TopicRepository.java
#Repository
public interface TopicRepository extends CrudRepository<Topic, String>{
}
TopicService.java
#Service
public class TopicService {
#Autowired
TopicRepository topicRepository;
public List<Topic> getAllTopics(){
List<Topic> topics = new ArrayList<>();
topicRepository.findAll().forEach(topics::add);
return topics;
}
public void addTopic(Topic topic){
// topics.add(topic);
topicRepository.save(topic);
}
}
While I am running the main class , I am getting the following error.
APPLICATION FAILED TO START
Description:
Field topicRepository in com.ibm.springboot.topics.TopicService
required a bean of type 'com.ibm.springboot.topics.TopicRepository'
that could not be found.
Action:
Consider defining a bean of type 'com.ibm.springboot.topics.TopicRepository' in your configuration.
I have checked all the related suggestion given here, but nothing clicked.Please help
Remove the #Repository annotation from your TopicRepository interface.
Should be (no annotation over it):
public interface TopicRepository extends CrudRepository{
}
EDIT
Change your:
#EnableJpaRepositories("com.ibm.springboot.topics.TopicRepository")
To:
#EnableJpaRepositories(basePackageClasses= {com.ibm.springboot.topics.TopicRepository.class})

Cucumber: no backend found when running from Spring Boot jar

I am creating a small testing framework that should utilize both Cucumber and the Spring Boot platform. The idea is to let the whole application be packaged as a single jar and run after the BDD features have been properly parametrized.
The framework starts in command line runner mode like this:
public class FwApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(FwApplication.class, args);
}
#Override
public void run(String... arg0) throws Exception {
JUnitCore.main(CucumberIntegration.class.getCanonicalName());
}
}
Then there is the CucumberIntegration class:
#RunWith(Cucumber.class)
#CucumberOptions(features = "config/features")
#ContextConfiguration(classes= AppConfiguration.class)
public class CucumberIntegration {
}
I have also some simple tests which run fine under my IDE, but when I try to package the application and run it over java -jar fw-0.0.1-SNAPSHOT.jar I get to see following:
There was 1 failure:
1) initializationError(com.fmr.bddfw.test.CucumberIntegration)
cucumber.runtime.CucumberException: No backends were found. Please make sure you have a backend module on your CLASSPATH.
at cucumber.runtime.Runtime.<init>(Runtime.java:81)
at cucumber.runtime.Runtime.<init>(Runtime.java:70)
(...)
All necessary jars are already in the one jar created by maven and it works fine under my IDE.
Any ideas what could help?
EDIT: Here my pom 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xxx</groupId>
<artifactId>fw</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>fw</name>
<description>BDD Testing Framework</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<cucumber.version>1.2.5</cucumber.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-test</artifactId>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-spring</artifactId>
<version>${cucumber.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Using the suggestion given by Marcus:
Step1: Create your custom MultiLoader class:
package cucumber.runtime.io;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
public class CustomMultiLoader implements ResourceLoader {
public static final String CLASSPATH_SCHEME = "classpath*:";
public static final String CLASSPATH_SCHEME_TO_REPLACE = "classpath:";
private final ClasspathResourceLoader classpath;
private final FileResourceLoader fs;
public CustomMultiLoader(ClassLoader classLoader) {
classpath = new ClasspathResourceLoader(classLoader);
fs = new FileResourceLoader();
}
#Override
public Iterable<Resource> resources(String path, String suffix) {
if (isClasspathPath(path)) {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = path.replace(CLASSPATH_SCHEME_TO_REPLACE, CLASSPATH_SCHEME) + "/**/*" + suffix;
org.springframework.core.io.Resource[] resources;
try {
resources = resolver.getResources(locationPattern);
} catch (IOException e) {
resources = null;
e.printStackTrace();
}
return convertToCucumberIterator(resources);
} else {
return fs.resources(path, suffix);
}
}
private Iterable<Resource> convertToCucumberIterator(org.springframework.core.io.Resource[] resources) {
List<Resource> results = new ArrayList<Resource>();
for (org.springframework.core.io.Resource resource : resources) {
results.add(new ResourceAdapter(resource));
}
return results;
}
public static String packageName(String gluePath) {
if (isClasspathPath(gluePath)) {
gluePath = stripClasspathPrefix(gluePath);
}
return gluePath.replace('/', '.').replace('\\', '.');
}
private static boolean isClasspathPath(String path) {
if (path.startsWith(CLASSPATH_SCHEME_TO_REPLACE)) {
path = path.replace(CLASSPATH_SCHEME_TO_REPLACE, CLASSPATH_SCHEME);
}
return path.startsWith(CLASSPATH_SCHEME);
}
private static String stripClasspathPrefix(String path) {
if (path.startsWith(CLASSPATH_SCHEME_TO_REPLACE)) {
path = path.replace(CLASSPATH_SCHEME_TO_REPLACE, CLASSPATH_SCHEME);
}
return path.substring(CLASSPATH_SCHEME.length());
}
}
Step2: Create an adapter between org.springframework.core.io.Resource and cucumber.runtime.io.Resource:
package cucumber.runtime.io;
import java.io.IOException;
import java.io.InputStream;
public class ResourceAdapter implements Resource {
org.springframework.core.io.Resource springResource;
public ResourceAdapter(org.springframework.core.io.Resource springResource) {
this.springResource = springResource;
}
public String getPath() {
try {
return springResource.getFile().getPath();
} catch (IOException e) {
try {
return springResource.getURL().toString();
} catch (IOException e1) {
e1.printStackTrace();
return "";
}
}
}
public String getAbsolutePath() {
try {
return springResource.getFile().getAbsolutePath();
} catch (IOException e) {
return null;
}
}
public InputStream getInputStream() throws IOException {
return this.springResource.getInputStream();
}
public String getClassName(String extension) {
String path = this.getPath();
if (path.startsWith("jar:")) {
path = path.substring(path.lastIndexOf("!") + 2);
return path.substring(0, path.length() - extension.length()).replace('/', '.');
} else {
path = path.substring(path.lastIndexOf("classes") + 8);
return path.substring(0, path.length() - extension.length()).replace('\\', '.');
}
}
}
Step3: Create your custom main class that uses your CustomMultiLoader:
package cucumber.runtime.io;
import static java.util.Arrays.asList;
import java.io.IOException;
import java.util.ArrayList;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.Runtime;
import cucumber.runtime.RuntimeOptions;
public class CucumberStaticRunner {
public static void startTests(String[] argv) throws Throwable {
byte exitstatus = run(argv, Thread.currentThread().getContextClassLoader());
System.exit(exitstatus);
}
public static byte run(String[] argv, ClassLoader classLoader) throws IOException {
RuntimeOptions runtimeOptions = new RuntimeOptions(new ArrayList<String>(asList(argv)));
ResourceLoader resourceLoader = new CustomMultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
Runtime runtime = new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
runtime.run();
return runtime.exitStatus();
}
}
Step4: Call your custom main class instead of cucumber.api.cli.Main.main:
String[] cucumberOptions = { "--glue", "my.test.pack", "--no-dry-run", "--monochrome", "classpath:features" };
CucumberStaticRunner.startTests(cucumberOptions);
Fixed it by following configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
You should add cucumber-java dependency
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
private static byte run(String[] argv, ClassLoader classLoader) throws IOException {
// cucumber/Spring Boot classloader problem
// CucumberException: No backends were found. Please make sure you have a backend module on your CLASSPATH
RuntimeOptions runtimeOptions = new RuntimeOptions(new ArrayList<String>(asList(argv)));
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
Reflections reflections = new Reflections(classFinder);
List<Backend> list = new ArrayList<>();
list.addAll(reflections.instantiateSubclasses(Backend.class, "cucumber.runtime", new Class[]{ResourceLoader.class}, new Object[]{resourceLoader}));
if (list.size() == 0) {
JavaBackend javaBackend = new JavaBackend(resourceLoader);
list.add(javaBackend);
}
Runtime runtime = new Runtime(resourceLoader, classLoader, list, runtimeOptions);
runtime.run();
return runtime.exitStatus();
}
I used below code in POM.xml file
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.4</version>
<scope>test</scope>
</dependency>
It is working fine now.

Resources