Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Springboot with Swagger

Swagger is an open source project used to generate the REST API documents for RESTful web services.

Add swagger and swagger-ui dependencies

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.7.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.7.0</version>
</dependency>

Add Swagger Config class

@PropertySource("classpath:swagger.properties")
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Bean
    public Docket api() {
        log.info("setting up Docket..");
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.folaukaveinga"))
                .paths(PathSelectors.any()).build().apiInfo(getApiInfo());
        
        log.info("docket setup!");
        
        return docket;
    }

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("Folau Kaveinga", "folaukaveinga.org", "folaukaveinga@gmail.com");
        return new ApiInfoBuilder()
                .title("Spring Data Tutorial")
                .description("Spring Data API")
                .version("1.0.0")
                .contact(contact)
                .build();
    }

}

Anotate controller classes

  1. Anotate Controller class with @Api
  2. Anotate methods with @ApiOperation
  3. Use @ApiParam to describe parameters
@Api(value = "users", produces = "Rest API for User operations", tags = "User Controller")
@RestController
@RequestMapping("/users")
public class UserController {

    private Logger      log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserService userService;

    @ApiOperation(value = "Get Member By Id")
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@ApiParam(name = "id", required = true, value = "id of member") @PathVariable("id") Long id) {
        log.info("get user by id: {}", id);

        return new ResponseEntity<>(userService.getById(id), HttpStatus.OK);
    }

}

Source code on Github

August 6, 2019

Springboot Mapstruct

 

A Data Transfer Object(DTO) is an object that is used to encapsulate data or domain model, and send it from one subsystem of an application to another. DTOs are most commonly used by the Services layer in an N-Tier application to transfer data between itself and the UI layer.Mapstruct is by far the best DTO generator I have worked with for many reasons. Here is the official site.

Installation with maven

...
<properties>
    <org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version> <!-- or newer version -->
            <configuration>
                <source>1.8</source> <!-- depending on your project -->
                <target>1.8</target> <!-- depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

Create a Mapper interface

@Mapper(componentModel = "spring", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper {
 
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
 
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);

}

Model

public class Car {
 
    private String make;
    private int numberOfSeats;
    private CarType type;
 
    //constructor, getters, setters etc.
}

DTO

public class CarDto {
 
    private String make;
    private int seatCount;
    private String type;
 
    //constructor, getters, setters etc.
}
....
Car car = new Car( "Morris", 5, CarType.SEDAN );
 
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );

 

 

August 6, 2019

Springboot Email

You can use Springboot to send out emails. All you need is access SMTP server. You can then use the JavaMailSender interface to send emails out.

Add dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

Add email SMTP server configuration settings to application.properties

#mail
spring.mail.host=smtp.gmail.com
spring.mail.username=username
spring.mail.password=password
spring.mail.port=587
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.debug=true
spring.mail.properties.mail.sender=senderEmail@gmail.com

EmailService

import java.io.IOException;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

@Service
public class EmailServiceImp implements EmailService {

    @Autowired
    private JavaMailSender mailSender;
    
    
    // This is for aws ses mail. Sender email needs to be verified first before using it as a sender email.
    @Value("${spring.mail.properties.mail.sender}")
    private String sender;

    @Override
    public boolean sendSimpleMail(String to, String subject, String msg) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setTo(to);
        simpleMailMessage.setSubject(subject);
        simpleMailMessage.setText(msg);
        simpleMailMessage.setFrom(sender);
        try {
            mailSender.send(simpleMailMessage);
            return true;
        } catch (Exception e) {
            System.out.println("Exception, send. msg: " + e.getMessage());
            return false;
        }
    }

    @Override
    public boolean sendAttachmentMail(String to, String subject, String msg, String attachmentPath) {
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(msg);
            helper.setFrom(sender);
            ClassPathResource attachment = new ClassPathResource(attachmentPath);
            helper.addAttachment(attachment.getFile().getName(), attachment.getFile());
            mailSender.send(message);
            return true;
        } catch (MessagingException e) {
            System.out.println("Exception, send. msg: " + e.getMessage());
            return false;
        } catch (IOException e) {
            System.out.println("Exception, send. msg: " + e.getMessage());
            return false;
        }

    }

    
    /*
     * It's recommended that when sending html emails that you use table to structure and style
     * your email.
     * */
    @Override
    public boolean sendHtmlMail(String to, String subject, String msg) {
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(msg, true);
            helper.setFrom(sender);
            mailSender.send(message);
            return true;
        } catch (MessagingException e) {
            System.out.println("Exception, send. msg: " + e.getMessage());
            return false;
        }
    }

    
    /*
     * It's recommended that when sending html emails that you use table to structure and style
     * your email.
     * */
    @Override
    public boolean sendHtmlWithInlineImageMail(String to, String subject, String msg, String logoPath) {
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(msg,true);
            helper.setFrom(sender);
            // cid:log
            helper.addInline("logo", new ClassPathResource(logoPath));
            
            mailSender.send(message);
            return true;
        } catch (MessagingException e) {
            System.out.println("Exception, send. msg: " + e.getMessage());
            return false;
        }
    }

}

Source code on Github

August 6, 2019

Springboot JMS

A production JMS server must be a stand alone server. What we have here is for demonstration purposes.

Add dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

Add configuration class

@Configuration
@EnableJms
public class JmsConfig {

    @Bean
    public JmsListenerContainerFactory<?> jmsFactory(ConnectionFactory connectionFactory,DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        return factory;
    }
    
    @Bean // Serialize message content to json using TextMessage
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }
}

Add a Sender

@Slf4j
@Component
public class Sender {

    @Autowired
    private JmsTemplate jmsTemplate;

    @Value("${queue.sender-receiver}")
    private String      queue;

    public void sendMail(Mail mail) {
        try {
            jmsTemplate.convertAndSend(queue, mail);
            log.info("Mail sent to queue, {}, at {}", queue, LocalDateTime.now());
        } catch (Exception e) {
            log.error("Mail not sent");
            log.error("Exception, msg: {}", e.getMessage());
        }

    }

}

Add a Receiver

@Slf4j
@Component
public class Receiver {

    @JmsListener(destination = "${queue.sender-receiver}", containerFactory = "jmsFactory")
    public void receiveMessage(Mail mail) {
        log.info("Received mail {}", LocalDateTime.now());
        try {
            log.info("mail={}", ObjectUtils.toJson(mail));
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

    }

}

Source code on Github

August 6, 2019

Springboot Cache

 

An application without cache is typically slow. Even great code will crawl when handling heavy traffic without cache. Caching can be a fast and relatively cheap way to increase performance.

Caching is a performance boost strategy you must implement into your application. Caching is nothing more than a hash table.

For Redis, all Redis data resides in-memory, in contrast to databases that store data on disk or SSDs. By eliminating the need to access disks, in-memory data stores such as Redis avoid seek time delays and can access data in microseconds. Redis features versatile data structures, high availability, geospatial, Lua scripting, transactions, on-disk persistence, and cluster support making it simpler to build real-time internet-scale apps.

I am going to show you how to implement caching into your Spring Boot application.

1. Include the following dependencies in your pom file.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

In your application.properties file, set Redis configurations. Also set spring.cache.type=redis.

2. Create a configuration class

@Configuration
@EnableCaching
public class CachingConfig{
	
	
    @Bean("customKeyGenerator")
    public KeyGenerator keyGenerator() {
        return new CustomKeyGenerator();
    }
	
private class CustomKeyGenerator implements KeyGenerator {
		  
	    public Object generate(Object target, Method method, Object... params) {
	    	StringBuilder strParams = new StringBuilder(target.getClass().getSimpleName());
	    	strParams.append("_");
			strParams.append(method.getName());
	    	for(Object param: params) {
				strParams.append("_");
				strParams.append(param);
			}
	    	System.out.println("key="+strParams.toString());
	        return strParams.toString();
	    }
}

}

3. Use @Cacheable to retrieve data

@Cacheable(value="users", key = "#id")
public User getById(Long id) {
	// retrieve User from db
	...
	return user;
}

4. Use @CachePut to update cached data

@CachePut(value="users", key = "#user.id")
public User update(User user) {
        ....
	return user;
}

5. Use @CacheEvict to delete cached data

@CacheEvict(value="users", key = "#id")
public Boolean delete(Long id) {
	....
	return true;
}
August 6, 2019