Giter Site home page Giter Site logo

thanus / reboot Goto Github PK

View Code? Open in Web Editor NEW
66.0 5.0 3.0 136 KB

ReBoot: a refactoring tool to automatically apply best practices in Java / Spring-Boot applications.

License: Apache License 2.0

Kotlin 98.76% Java 1.24%
metaprogramming refactoring spring-boot rascal java kotlin spring transformation

reboot's Introduction

ReBoot

Build Status Maven Central Codacy Badge codecov

A refactoring tool to automatically apply best practices in Java / Spring-Boot applications. ReBoot performs the following refactorings on a project:

The initial version of ReBoot was written in Rascal, see branch reboot-v1.

Refactorings

Request Mapping

Spring provides HTTP method specific shortcut variants for @RequestMapping. These custom annotations (@GetMapping, @PostMapping, etc) are less verbose and more expressive than @RequestMapping. This refactoring is also applied to projects using Spring Cloud OpenFeign, as they also reuse Spring annotations.

Refactoring diff

-import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.GetMapping;

@RestController
@RequestMapping("/users")
public class UsersController {
-   @RequestMapping(method = RequestMethod.GET)
+   @GetMapping
    public ResponseEntity<List<User>> getUsers() {
        // code
    }

-   @RequestMapping(path = "/{id}", method = RequestMethod.GET)
+   @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
        // code
    }
}

Explicit web annotation

URI Variables can be named explicitly, like @PathVariable("id") Long id, but this is redundant. This detail can be left out if the names are the same. This refactoring is also applied to projects using Spring Cloud OpenFeign, as they also reuse Spring annotations. This refactoring is not only applicable for PathVariable but also RequestParam, RequestHeader, RequestAttribute, CookieValue, ModelAttribute, SessionAttribute. For example, for @PathVariable:

Refactoring diff

@RestController
@RequestMapping("/users")
public class UsersController {
    @GetMapping("/{id}")
-   public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
+   public ResponseEntity<User> getUser(@PathVariable Long id) {
        // code
    }
}

Explicit mandatory web annotation

The attribute required set to true on annotations like @PathVariable is not necessary as this is default already. This refactoring is also applied to projects using Spring Cloud OpenFeign, as they also reuse Spring annotations. This refactoring is not only applicable for PathVariable but also RequestParam, RequestHeader, RequestAttribute, CookieValue, ModelAttribute, SessionAttribute. For example, for @PathVariable:

Refactoring diff

@RestController
@RequestMapping("/users")
public class UsersController {
    @GetMapping("/{id}")
-   public ResponseEntity<User> getUser(@PathVariable(required = true) Long id) {
+   public ResponseEntity<User> getUser(@PathVariable Long id) {
        // code
    }
}

Field injection with Spring Autowired

Dependency injection with field injection is not recommended. Instead, constructor injection should be used, leading to safer code and easier to test. This is explained in more detail in article why-field-injection-is-evil.

Refactoring diff

-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;

+@RequiredArgsConstructor
@RestController
@RequestMapping("/users")
public class UsersController {
-   @Autowired
-   private UsersService usersService;
-   @Autowired
-   private UsernameService usernameService;
+   private final UsersService usersService;
+   private final UsernameService usernameService;
}

Field injection with Mockito

Just like the above refactoring, it is not recommended to do field injection with Mockito for the same reasons. This is explained in more detail in article Mockito: Why You Should Not Use InjectMocks Annotation to Autowire Fields.

Refactoring diff

-import org.mockito.InjectMocks;
-import org.mockito.Mock;
+import org.mockito.Mockito;

@ExtendWith(value = MockitoExtension.class)
class UsersControllerTest {
-   @Mock
-   private UsersService usersService;
-   @Mock
-   private UsernameService usernameService;
-   @InjectMocks
-   private UsersController usersController;
+   private UsersService usersService = Mockito.mock(UsersService.class);
+   private UsernameService usernameService = Mockito.mock(UsernameService.class);
+   private UsersController usersController = new UsersController(usersService, usernameService);
}

Usage

Building from source

After cloning the project, you can build it from source with:

./mvnw clean install

Running ReBoot jar

cd reboot-core
java -jar target/reboot-core-1.1.0-SNAPSHOT-jar-with-dependencies.jar /path/to/project

Running reboot-maven-plugin

Add reboot-maven-plugin to your POM:

<build>
    <plugins>
        <plugin>
            <groupId>nl.thanus</groupId>
            <artifactId>reboot-maven-plugin</artifactId>
            <version>1.0.0</version>
        </plugin>
    </plugins>
</build>

By default, reboot-maven-plugin uses ${project.basedir} as path to refactor. If you want to specify another path, you can use the property directory:

<build>
    <plugins>
        <plugin>
            <groupId>nl.thanus</groupId>
            <artifactId>reboot-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
                <directory>/path/to/project</directory>
            </configuration>
        </plugin>
    </plugins>
</build>

Run plugin:

mvn nl.thanus:reboot-maven-plugin:1.0.0:reboot

Excluding refactorings

Refactorings can be excluded from ReBoot.

To exclude when you are running the ReBoot jar add the flag -e or --excluded with refactoring you want to exclude. For example:

java -jar target/reboot-core-1.1.0-SNAPSHOT-jar-with-dependencies.jar /path/to/project -e request-mappings -e autowired-field-injection

To exclude refactorings from the maven plugin, add them to the configuration tag like this:

<excluded>
    <refactoring>request-mappings</refactoring>
    <refactoring>autowired-field-injection</refactoring>
</excluded>

The excluded refactorings should be named as:

  • request-mappings
  • web-annotations
  • autowired-field-injection
  • mockito-field-injection

Contributions are welcome!

Feel free to suggest and implement improvements.

reboot's People

Contributors

dependabot[bot] avatar keso-rupert avatar thanus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

reboot's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.