简体   繁体   English

Spring Boot-会话作用域组件上的设置器无法从单例服务中使用-字段为null

[英]Spring boot - setters on session scoped component not working from singleton service - fields are null

I have a simple service behind a REST controller in Spring Boot. 我在Spring Boot中的REST控制器后面有一个简单的服务。 The service is a singleton (by default) and I am autowiring a session-scoped bean component used for storing session preferences information and attempting to populate its values from the service. 该服务是单例(默认情况下),我正在自动装配一个会话范围的Bean组件,该组件用于存储会话首选项信息,并尝试从服务中填充其值。 I call setters on the autowired component, but the fields I am setting stay null and aren't changed. 我在自动装配的组件上调用了setter,但是我设置的字段保持为空且未更改。

Have tried with and without Lombok on the bean; 试过在豆子上加上或不加上龙目岛; also with and without implementing Serializable on FooPref; 也可以在FooPref上实现或不实现Serializable; also copying properties from FooPrefs to another DTO and returning it; 还将属性从FooPrefs复制到另一个DTO并返回它; also injecting via @Autowired as well as constructor injection with @Inject. 也可以通过@Autowired进行注入,以及通过@Inject进行构造函数注入。 The fields stay null in all of those cases. 在所有这些情况下,该字段均保留为空。

Running Spring Boot (spring-boot-starter-parent) 1.5.6.RELEASE, Java 8, with the spring-boot-starter-web. 运行Spring Boot(spring-boot-starter-parent)1.5.6.RELEASE,Java 8,带有spring-boot-starter-web。

Session-scoped component: 会话范围的组件:

@Component
@SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Data
@NoArgsConstructor
public class FooPrefs implements Serializable {
    private String errorMessage;
    private String email;
    private String firstName;
    private String lastName;
}

REST Controller: REST控制器:

@RestController
@RequestMapping("/api/foo")
public class FooController {

    @Autowired
    private FooPrefs fooPrefs;

    private final FooService fooService;

    @Inject
    public FooController(FooService fooService) {
        this.fooService = fooService;
    }

    @PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
    public FooPrefs updatePrefs(@RequestBody Person person) {
        fooService.updatePrefs(person);

        // These checks are evaluating to true
        if (fooPrefs.getEmail() == null) {
            LOGGER.error("Email is null!!");
        }
        if (fooPrefs.getFirstName() == null) {
            LOGGER.error("First Name is null!!");
        }
        if (fooPrefs.getFirstName() == null) {
            LOGGER.error("First Name is null!!");
        }
        return fooPrefs;
    }
}

Service: 服务:

@Service
@Scope(value = "singleton")
@Transactional(readOnly = true)
public class FooService {

    @Autowired
    private FooPrefs fooPrefs;

    @Inject
    public FooService(FooRepository fooRepository) {
        this.fooRepository = fooRepository;
    }

    public void updatePrefs(Person person) {
        fooRepository.updatePerson(person);

        //the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
        fooPrefs.setEmail(person.getEmail());
        fooPrefs.setFirstName(person.getFirstName());
        fooPrefs.setLastName(person.getLastName());
    }
}

I discovered my problem. 我发现了我的问题。 Fields were being added to my FooPrefs session-managed object and were breaking my client. 字段被添加到我的FooPrefs会话管理的对象中,并且破坏了我的客户端。 The setters were actually working and being nulled out by some error handling code. 设置器实际上正在工作,并且被一些错误处理代码所消除。

Edits per below fixed the JSON serialization problems: 根据以下内容进行编辑可解决JSON序列化问题:

Session-scoped component (no change) 会话范围的组件(不变)

New Dto 新Dto

@Data
@NoArgsConstructor
public class FooPrefsDto {
    private String errorMessage;
    private String email;
    private String firstName;
    private String lastName;
}

Controller (updated) 控制器(已更新)

@RestController
@RequestMapping("/api/foo")
public class FooController {

    private final FooService fooService;

    @Inject
    public FooController(FooService fooService) {
        this.fooService = fooService;
    }

    @PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
    public FooPrefsDto updatePrefs(@RequestBody Person person) {
        FooPrefsDto result = fooService.updatePrefs(person);

        // results coming back correctly now
        if (result.getEmail() == null) {
            LOGGER.error("Email is null!!");
        }
        if (result.getFirstName() == null) {
            LOGGER.error("First Name is null!!");
        }
        if (result.getFirstName() == null) {
            LOGGER.error("First Name is null!!");
        }
        return result;
    }
}

Service (updated) 服务(已更新)

@Service
@Scope(value = "singleton")
@Transactional(readOnly = true)
public class FooService {

    @Autowired
    private FooPrefs fooPrefs;

    @Inject
    public FooService(FooRepository fooRepository) {
        this.fooRepository = fooRepository;
    }

    public FooPrefsDto updatePrefs(Person person) {
        fooRepository.updatePerson(person);

        //the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
        fooPrefs.setEmail(person.getEmail());
        fooPrefs.setFirstName(person.getFirstName());
        fooPrefs.setLastName(person.getLastName());
        return getFooPrefsDto();
    }

    private FooPrefsDto getFooPrefsDto() {
        FooPrefsDto retDto = new FooPrefsDto();
        retDto.setEmail(fooPrefs.getEmail());
        retDto.setLastName(fooPrefs.getLastName());
        retDto.setFirstName(fooPrefs.getFirstName());
        return retDto;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM