The engineers of the NOREL team are modernizing the technology used, and there was a talk that "I want to write a system written in Java / Spring Boot in Kotlin anyway", so I will proceed with correspondence so that it can be developed in Kotlin. I am.
I often see articles such as starting with Kotlin (Gradle) from the beginning, but I could not find many articles that correspond to Kotlin (Maven) while it was written in Java, so I tried to deal with it.
Basically, Spring Boot implements only REST API.
--Since development in Java is progressing in parallel, converting all code from Java to Kotlin will be postponed this time. --Controller / Service can be written in Kotlin --Leave the data access layer such as JPA as Java ――I want to make everything Kotlin in the end
Also, this work was done on IntelliJ.
--For the pom.xml settings, I referred to the following Kotlin official website.
--Definition of Kotlin version
pom.xml
<properties>
...
<java.version>1.8</java.version>
+ <kotlin.version>1.2.10</kotlin.version>
+ <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>
--Added Kotlin dependency library
pom.xml
<dependencies>
・ ・ ・
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ <version>${kotlin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-reflect</artifactId>
+ <version>${kotlin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-test</artifactId>
+ <version>${kotlin.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
--Build settings
Originally I didn't use maven-compiler-plugin
, but each package is ready for development in both Java and Kotlin.
I'm using maven-compiler-plugin
to separate by.
In addition, spring is defined as compilerPlugins so that various annotations used in Spring can be used. As mentioned in the documentation, defining a spring plugin seems to eliminate the need to define all-open.
pom.xml
<build>
<finalName>${project.name}</finalName>
- <sourceDirectory>src/main/java</sourceDirectory>
- <testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${resources.directory}</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
+ <plugin>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <version>${kotlin.version}</version>
+ <configuration>
+ <compilerPlugins>
+ <plugin>spring</plugin>
+ </compilerPlugins>
+ </configuration>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <goals> <goal>compile</goal> </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
+ <sourceDir>${project.basedir}/src/main/java</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <goals> <goal>test-compile</goal> </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+ <sourceDir>${project.basedir}/src/test/java</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-allopen</artifactId>
+ <version>${kotlin.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <executions>
+ <!-- Replacing default-compile as it is treated specially by maven -->
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <!-- Replacing default-testCompile as it is treated specially by maven -->
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>java-compile</id>
+ <phase>compile</phase>
+ <goals> <goal>compile</goal> </goals>
+ </execution>
+ <execution>
+ <id>java-test-compile</id>
+ <phase>test-compile</phase>
+ <goals> <goal>testCompile</goal> </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
</build>
Now you are ready to write Kotlin on IntelliJ.
When I asked the members who usually use STS to check the correspondence so far, it did not work well and I was a little addicted to it, so I will also describe how to deal with STS.
--Install the Kotlin Plugin for Eclipse
from the Eclipse marketplace.
--Since src / main / kotlin
is not recognized as a build path, check the kotlin folder with Add File from Source of Projects> Properties> Java Build Path
.
Same for src / test / kotlin
--Right-click on the project and run Configure Kotlin> Add Kotlin Nature
In the figure below, you can not select it because it has already been added Kotlin Nature, but you can select it before execution.
Now it compiles on STS and you can develop on Kotlin.
Since the conversion function of IntelliJ is excellent, I basically converted it with IntelliJ. It's scary to put them all together at once, so I converted one code or several codes at a time.
Select the code you want to convert and convert it to Kotlin code with Code> Convert Java File to Kotlin File
.
Also, since the package is still under src / main / java
, move it under the same package under src / main / kotlin
.
This is also nicely refactored with Refactor> Move ...
in IntelliJ.
For example, the code below
@Service
public class HogeService {
@Autowired
private HogeRepository hogeRepository;
}
In Kotlin, you can also declare it with lateinit
, but this time I defined it with constructor injection
.
@Service
class HogeService(
private val hogeRepository: HogeRepository
) {
}
When using Lombok, I sometimes got a compile error when converting to Kotlin.
Basically, the class that converts to Kotlin and the class that is referenced from Kotlin are solved by Delombok.
Use the IntelliJ lombok plugin.
It will remove the Lombok conversion from Refactor> Delombok
.
--Slf4j annotation
You can omit the logger declaration and write code that outputs logs suddenly. If you use Kotlin, the following code cannot resolve the log variable and a compile error will occur.
@Service
@Slf4j
public class HogeService {
public void hoge() {
log.info("hoge");
}
}
In kotlin, it can be used by initializing the logger with companion object
.
@Service
class HogeService {
companion object {
private val log = LoggerFactory.getLogger(HogeService::class.java)
}
}
Some people have tried the DI method with annotations, so I would like to consider making it easier. http://saiya-moebius.hatenablog.com/entry/2017/11/08/033932
--Data annotation
I read the following Lombokized Java code from Kotlin, and when I try to get the hoge, it says that it is private and not accessible. In this case, as described above, it was converted to Delombok. (If everything becomes Kotlin, you don't have to use Lombok in the first place ...)
@Entity
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class Hoge extends AbstractEntity {
@Column(name = "hoge")
private String hoge;
}
At this point, some code is now Kotlinized and works. However, I've had problems several times while I was actually writing the code, so it's possible that I'll continue to have problems. I think that I should add more and more how to deal with it.
Recommended Posts