简体   繁体   English

实体中的Spring Roo Service自动接线始终为空(将JPA存储库与@RooJpaEntity结合使用)

[英]Spring roo Service auto wiring in entities is always null (Using JPA Repository with @RooJpaEntity)

I've been looking for a way to call some method from a service, when my entity is saved. 保存实体时,我一直在寻找一种从服务中调用某些方法的方法。

My App was created using roo 1.2.4.RELEASE 我的应用是使用Roo 1.2.4.RELEASE创建的

I have a Balance Entity called SaldoCliente and a ClientAction Entity called AuxCliente. 我有一个称为SaldoCliente的Balance实体和一个名为AuxCliente的ClientAction实体。

I need to update a client balance every time a new ClientAction entity gets persisted. 每当新的ClientAction实体持续存在时,我都需要更新客户余额。

This is my code: 这是我的代码:

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    static private SaldoClienteService saldoClienteService;


...


    @PostConstruct
    public void init() 
    {
        System.out.println("Initializing with dependency ["+ saldoClienteService + "]");
    }

    @PostPersist
    private void afectaSaldoCliente(/*Long idTrans, Cliente, Integer cargo, BigDecimal importe, Integer creditos*/) {
      if (saldoClienteService == null) {
          System.out.println("saldoClienteService FUE NULL");
      }
...

I don't know why saldoClienteService is always null. 我不知道为什么saldoClienteService总是为null。

(Note I don't want a saldoClienteService field saved in my DB, hence the @Transient annotation) (请注意,我不希望在数据库中保存saldoClienteService字段,因此不需要@Transient注释)

I've been searching for a solution without success. 我一直在寻找没有成功的解决方案。 Many of the explanations say something like this where says: You need <context:annotation-config/> (or <context:component-scan/>) to enable @PostConstruct handling. 许多解释说,像这样在那里说: You need <context:annotation-config/> (or <context:component-scan/>) to enable @PostConstruct handling.

And I do have <context:component-scan> in my applicationContext.xml (created by Roo). 而且我的applicationContext.xml(由Roo创建)中确实有<context:component-scan>

The documentation says: 该文件说:

By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected. 默认情况下,将检测到Spring提供的@ Component,@ Repository,@ Service和@Controller构造型。 Note: This tag implies the effects of the 'annotation-config' tag, activating @Required, @Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit annotations in the component classes, which is usually desired for autodetected components (without external configuration). 注意:此标记暗含“ annotation-config”标记的作用,在组件类中激活@ Required,@ Autowired,@ PostConstruct,@ PreDestroy,@ Resource,@ PersistenceContext和@PersistenceUnit批注,这对于自动检测到的组件通常是必需的(无需外部配置)。

And at least the @Autowired annotation works everywhere but there. 至少@Autowired注释可以在任何地方使用。

Does anybody have some pointers? 有人有指针吗?

------------------ EDITED ----------------- ------------------编辑-----------------

First of all: I want to thank @Sotirios and @Ralph for taking the time to help me. 首先:感谢@Sotirios和@Ralph抽出宝贵的时间来帮助我。

If I remove "static" from the field, it's the same. 如果我从字段中删除“静态”,则相同。 The injected fields are always null in my Entities. 在我的实体中,注入的字段始终为null。 (See my comments in this question, I added that because of a "possible" solution). (请参阅我在此问题中的评论,我补充说这是因为“可能”的解决方案)。

I'm having trouble also with another class I need injected. 我在另一个需要注射的课程上也遇到了麻烦。 I added this to the same class as before (AuxClientes): 我将此添加到与以前相同的类中(AuxClientes):

@Transient
@Autowired
private ConfigUser configUser;

And configUser is always null, also. 并且configUser始终也为null。

This is the beginning of the other class, in case it matters. 如果需要的话,这是另一堂课的开始。

@RooJavaBean(settersByDefault=false)
public class ConfigUser {
...

and ofcourse, in applicationContext.xml: 当然,在applicationContext.xml中:

<bean class="com.i4b.adminctes.util.ConfigUser" id="appConfigUser" />

I'm successfully using configUser in constructors, services and repositories. 我在构造函数,服务和存储库中成功使用configUser。 But can't use it in Entities. 但不能在实体中使用它。

If you think I should post any other part of my code, just let me know. 如果您认为我应该发布代码的其他部分,请告诉我。

--------------- EDIT 2 ------------------ ---------------编辑2 ------------------

The same happens with all my entities. 我所有的实体也一样。

--------------- EDIT 3.a ------------------ ---------------编辑3.a ------------------

I changed the question title, for a better one. 我更改了问题标题,以获得更好的标题。 Before it was: 在此之前:

Spring roo (service autowiring) Entity not calling @PostConstruct . Spring Roo(服务自动装配)实体未调用@PostConstruct。 (Using JPA Repository with @RooJpaEntity) (通过@RooJpaEntity使用JPA存储库)

--------------- EDIT 3.b ------------------ ---------------编辑3.b ------------------

I have just created a minimal test project. 我刚刚创建了一个最小的测试项目。

// Spring Roo 1.2.4.RELEASE [rev 75337cf] log opened at 2013-11-13 11:36:27
project --topLevelPackage org.example --projectName TestAutowiredOnEntities --java 7 --packaging WAR
jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY 
entity jpa --class ~.domain.MyEntity --testAutomatically --activeRecord false
field string --fieldName text 
repository jpa --interface ~.repository.MyEntityRepository --entity ~.domain.MyEntity
service type --interface ~.service.MyEntityService --entity ~.domain.MyEntity
web mvc setup 
web mvc all --package org.example.web

Edited the service: 编辑了服务:

package org.example.service;

public class MyEntityServiceImpl implements MyEntityService {

    @Override
    public String testAutowire() {
        return "Some data";
    }
}

Edited the entity: 编辑实体:

package org.example.domain;
import javax.persistence.PrePersist;
import javax.persistence.Transient;

import org.example.service.MyEntityService;
import org.example.service.MyEntityServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.entity.RooJpaEntity;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {

    @Transient
    @Autowired
    MyEntityService myEntityService; 

    /**
     */
    private String text;

    @PrePersist
    public void prePersist() {
        if (myEntityService == null) {
            System.out.println("myEntityService IS NULL");
        } else {
            String data=myEntityService.testAutowire();
            System.out.println("it works: " + data);
            this.text = data;
        }
    } 
}

And edited the create.jspx to hide the service field. 并编辑了create.jspx以隐藏服务字段。 otherwise it doesn't let you save. 否则,它不会让您保存。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <jsp:output omit-xml-declaration="yes"/>
    <form:create id="fc_org_example_domain_MyEntity" modelAttribute="myEntity" path="/myentitys" render="${empty dependencies}" z="T0LoTr6PZAwfIQHkjOZMmPW7cO8=">
        <field:input field="myEntityService" id="c_org_example_domain_MyEntity_myEntityService" render="false" z="12sHnsW2dWYyuD+vDtbTve/jWuI="/>
        <field:input field="text" id="c_org_example_domain_MyEntity_text" z="jUCTnP7E3pYPcZcfGn1tyJ2VeFI="/>
    </form:create>
    <form:dependency dependencies="${dependencies}" id="d_org_example_domain_MyEntity" render="${not empty dependencies}" z="Un0bJ/PmWmczxoVTom9NowwIRWk="/>
</div>

Then executed the application and created a new "My Entity". 然后执行该应用程序并创建一个新的“我的实体”。 Leaving the field empty, I preassed the save button. 将字段留空,我预言了保存按钮。

The log shows: 日志显示:

INFO: Reloading Context with name [/testAutowiredOnEntities] is completed
nov 13, 2013 2:31:52 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
myEntityService IS NULL

And the entity has an empty text field. 并且该实体具有一个空文本字段。

Just to be sure, I added @Component to "MyEntity" class: 可以肯定的是,我在@MyEntity类中添加了@Component:

...
@Component
@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {
...

Nothing changed. 没有改变。 The service is still null. 该服务仍然为空。

I really hope it helps someone more knowledgable than me to help me find a solution. 我真的希望它能帮助比我更了解的人帮助我找到解决方案。

Thank you all. 谢谢你们。

In the mean time, I'll re-read the documentation section @Ralph pointed out. 同时,我将重新阅读@Ralph指出的文档部分。 I'm obviously doing something wrong. 我显然做错了。 I don't bielieve I'm the only one needing this. 我不相信我是唯一需要这个的人。

Again: Thank you all 再次:谢谢大家

Spring does not inject in static fields. Spring不会在static字段中注入。

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    private SaldoClienteService saldoClienteService;

    @PostPersist
    void afectaSaldoCliente() {
       this.saldoClienteService.doWhatYouWant();
    }

}

regarding update #2 关于更新#2

It looks like ConfigUser is an Hibernate/JPA/Whatever Entity but not an Spring Bean. 看起来ConfigUser是一个Hibernate / JPA /任何实体,但不是Spring Bean。 But you can only inject Spring Beans (like Services, Dao, ... (Every thing that has an @Component , @Controller , @Service , @Repository annotation*.)) 但是,您只能注入Spring Bean(例如Services,Dao,...(每一个具有@Component @Controller@Service@Repository @Controller@Service @Controller@Service @Repository批注*的东西)。)

And you can only inject in Spring Beans or Classes annotated with @Configurable (requires AspectJ) See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring 而且,您只能注入使用@Configurable注释的Spring Bean或类(需要AspectJ), 请参见Spring参考第7.8.1章,使用AspectJ通过Spring依赖注入域对象

Using @Configurable is the way Spring-Roo does (There must be a file AuxCliente_Roo_Configurable.aj next to your Entity (In Eclipse it needs to disable the "Hide generates Spring Roo ITDs"-Filter to display this file in the Package Explorer)). 使用@Configurable是Spring-Roo的方式(在实体旁边必须有一个文件AuxCliente_Roo_Configurable.aj (在Eclipse中,它需要禁用“隐藏生成Spring Roo ITD” -Filter才能在Package Explorer中显示此文件)) 。


* There are some more Ways that an object become a spring bean, but this does not matter here *将对象变成弹跳豆还有更多的方法,但这并不重要

Finally got it working. 终于成功了。

As I mentioned in my last comment to @Ralph: adding @Configurable annotation did the trick. 正如我在对@Ralph的最后评论中提到的那样:添加@Configurable批注可以解决问题。

If the class looks like the following, the autowiring works: 如果该类如下所示,则自动装配有效:

@Configurable                <--- added this
@RooPlural("Tarjetas")
@RooJavaBean
@RooToString
@RooJpaEntity
@Table(name = "TARJETAS")
public class Tarjeta {

    @Autowired
    @Transient
    private ConfigUser configUser;

...

But at the end I decided to use a helper class, in order to avoid all the Spring roo generated code for this attribute. 但是最后,我决定使用一个帮助器类,以避免所有Spring roo为该属性生成代码。 I don't want to add a private getter for configUser in order to prevent the Spring Roo's public one to exist and mark 'render="false"' in all the scaffolded views. 我不想为configUser添加一个私有的getter来防止Spring Roo的public的存在并在所有支架视图中将'render =“ false”'标记为。

Now I have: 我现在有:

@Configurable
@RooJavaBean
public class Helper {

    @Autowired
    private ConfigUser configUser;

    @Autowired
    private SaldoClienteService saldoClienteService;
}

When I need the autowired bean, I use something like this: 当我需要自动装配的bean时,可以使用如下代码:

ConfigUser configUser = new Helper().getConfigUser();

Again: Thank you very much @Ralph 再次:非常感谢@Ralph

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

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