I am new to springboot and am trying to follow this example: https://github.com/eugenp/tutorials/tree/master/spring-caching-2
In my app I keep getting "error: variable myApplicationService not initialized in the default constructor" but in comparison to the tutorial I am following, I don’t understand how it gets initialized, this is my controller:
package com.springbootredis.controllers;
import com.springbootredis.service.MyApplicationService;
import lombok.AllArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@AllArgsConstructor
@RequestMapping(value = "/person", produces = { MediaType.APPLICATION_JSON_VALUE })
public class PersonController {
private final MyApplicationService myApplicationService;//ERROR HERE
@GetMapping("/uuid")
public String generateRandomUUID() {
return UUID.randomUUID().toString();
}
@GetMapping("/addperson/{name}")
public String addPerson(@PathVariable String name) {
String ret = myApplicationService.addNewPerson(name);
return "Added person with name: " + name + " and id: " + ret;
}
@GetMapping("/deleteperson/{id}")
public String deletePerson(@PathVariable String id) {
String ret = myApplicationService.delete(id);
return "Deleted person. ID:" + id + " Name: " + ret;
}
@GetMapping("/updateperson/{id}/{name}")
public String updatePerson(@PathVariable String id, @PathVariable String name) {
myApplicationService.updatePerson(id, name);
return "Updated person. ID:" + id + " with Name: " + name;
}
@GetMapping("/getperson/{id}")
public String getPerson(@PathVariable String id) {
String ret = myApplicationService.findById(id);
return "Got person. ID:" + id + " Name: " + ret;
}
}
I tried autowired annotation but it says it is not recommended, and the build still fails. My build.gradle looks like this:
plugins {
id 'org.springframework.boot' version '2.7.1'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'war'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-data-redis:2.7.0")
implementation("org.springframework.boot:spring-boot-starter-cache:2.7.1")
implementation("org.projectlombok:lombok:1.18.24")
implementation("org.springframework.boot:spring-boot-dependencies:2.7.1")
runtimeOnly("mysql:mysql-connector-java:8.0.29")
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
Any help/pointers would be much appreciated.
2
Answers
To resolve my issue I added the following to the build.gradle file under the dependencies section:
Edit: (For completeness’ sake) As you’ve already found out, the
annotationProcessor
entry for Lombok is missing from yourbuild.gradle
file. In addition, your Lombok entry can becompileOnly
and does not need to be included at runtime.Original Answer follows.
Your code as-is should still work. As mentioned by @m-deinum, you should also avoid doing manual dependency management on Spring versions.
That said, Lombok does its magic via Annotation Processing, a feature that might not be enabled by default in your IDE Project.
One possible culprit for your error is that this feature is disabled, hence Lombok is not generating the constructor and only a default, no-args constructor is available. Once you enable it, the compile-error should go away.
That said, I’ve found
@AllArgsConstructor
to not be very robust when designing classes. Prefer@RequiredArgsConstructor
or simply explicit constructors and design your classes to have immutable state.