2012-08-28 26 views
20

मैं एक जेपीए EntityListener में एक स्प्रिंग निर्भरता सुई कोशिश कर रहा हूँ में एक स्प्रिंग निर्भरता इंजेक्शन।एक जेपीए EntityListener

@RooJavaBean 
@RooToString 
@RooJpaActiveRecord 
@EntityListeners(PliListener.class) 
public class Pli implements Serializable{ 
... 

लेकिन, मेरा निर्भरता (अर्थात evenementPliRepository) हमेशा अशक्त है:

@Configurable(autowire = Autowire.BY_TYPE, dependencyCheck = true) 
public class PliListener { 

    @Autowired 
    private EvenementPliRepository evenementPliRepository; 

    @PostPersist 
    void onPostPersist(Pli pli) { 
     EvenementPli ev = new EvenementPli(); 
     ev.setPli(pli); 
     ev.setDateCreation(new Date()); 
     ev.setType(TypeEvenement.creation); 
     ev.setMessage("Création d'un pli"); 
     System.out.println("evenementPliRepository: " + evenementPliRepository); 
     evenementPliRepository.save(ev); 
    } 


} 

यहाँ मेरी इकाई वर्ग है: यहाँ मेरी श्रोता वर्ग है।

किसी को भी कृपया मदद कर सकते हैं?

+0

भी देखें http://stackoverflow.com/questions/8616146/eventlisteners-using- हाइबरनेट -4-0-साथ-वसंत-3-1-0-रिलीज – Ralph

+0

मुझे भी एक ही समस्या का सामना करना पड़ रहा था और एक समाधान मिला और उसने इसे किसी अन्य पोस्ट पर उत्तर दिया है http://stackoverflow.com/questions/22171221/how- to-inject-entitymanager-in-entitylisteners/42222592 # 42222592 –

उत्तर

2

मेरा मानना ​​है कि ऐसा इसलिए है क्योंकि यह श्रोता बीन वसंत के नियंत्रण में नहीं है। वसंत इसे तुरंत नहीं कर रहा है, वसंत कैसे जान सकता है कि उस बीन को कैसे ढूंढें और इंजेक्शन कैसे करें?

मैंने उस पर कोशिश नहीं की है, लेकिन ऐसा लगता है कि आप वसंत नियंत्रण गैर-वसंत-तत्काल बीन्स के लिए स्प्रिंग कॉन्फ़िगर करने योग्य एनोटेशन के साथ एस्पेक्टजे वीवर का उपयोग कर सकते हैं।

http://static.springsource.org/spring/docs/3.1.2.RELEASE/spring-framework-reference/html/aop.html#aop-using-aspectj

+0

हैलो और एड्रियन धन्यवाद। मैंने अपनी कॉन्फ़िगरेशन में '<संदर्भ: वसंत-कॉन्फ़िगर />' जोड़ा है। मेरे पास पीओएम में एओपी * .जेर्स हैं। मुझे नहीं लगता कि मुझे कुछ याद आ रही है। अभी भी 'evenementPliRepository' ** शून्य ** है। मैं क्या खो सकता है के बारे में कोई अन्य विचार ?? – balteo

+0

क्या आपके पास एजेंट शुरू हुआ है? रेफरी से उद्धृत: 'आगे, कुछ वातावरण में, यह समर्थन एप्लिकेशन सर्वर की लॉन्च स्क्रिप्ट में कोई संशोधन किए बिना लोड-टाइम बुनाई को सक्षम बनाता है जिसे जोड़ने के लिए आवश्यक होगा -जवाजेंट: पथ/से/aspectjweaver.jar या (जैसा कि हम वर्णन करते हैं बाद में इस खंड में) -जवाजेंट: पथ/से/org.springframework.instrument- {version} .jar (पहले वसंत-एजेंट.जर नाम दिया गया था)। लेकिन ईमानदार होने के लिए, मैंने वास्तव में पहले इस सुविधा की कोशिश नहीं की है, शायद इस पर अन्य प्रतिबंध हैं जिन्हें मुझे पता नहीं है –

+0

मैं इसे जांचने जा रहा हूं। मैं यह भी महसूस कर रहा हूं कि क्योंकि मैं स्प्रिंग रू का उपयोग करता हूं, '@ कॉन्फ़िगर करने योग्य' पहले से ही आर द्वारा स्थापित किया गया है। मुझे यह भी कहता है कि मुझे निर्भरता के मुद्दों के बारे में कोई चेतावनी नहीं है ... – balteo

13

राज्यविहीन फलियों पर निर्भरता इंजेक्षन करने के लिए एक हैक,, इसे "स्थिर" निर्भरता को परिभाषित एक सेटर विधि ताकि वसंत निर्भरता (स्थिर निर्भरता को यह बताए) इंजेक्षन कर सकते हैं बनाने के लिए है।

निर्भरता को स्थिर के रूप में घोषित करें।

static private EvenementPliRepository evenementPliRepository; 

एक विधि बनाएं ताकि वसंत इसे इंजेक्ट कर सके।

@Autowired 
public void init(EvenementPliRepository evenementPliRepository) 
{ 
    MyListenerClass.evenementPliRepository = evenementPliRepository; 
    logger.info("Initializing with dependency ["+ evenementPliRepository +"]"); 
} 

अधिक जानकारी पर: http://blog-en.lineofsightnet.com/2012/08/dependency-injection-on-stateless-beans.html

+0

@SotiriosDelimanolis क्या यह वास्तव में किसी के लिए काम करता था? मैंने यह कोशिश की है, साथ ही सेटर्स पर '@Autowired' डालने और सेम अभी भी शून्य हैं।मैंने सत्यापित किया है कि '@ पोस्ट कॉन्स्ट्रक्ट' विधि कहा जा रहा है। – testing123

+0

@SotiriosDelimanolis निश्चित रूप से, मुझे बहुत सारे दृष्टिकोण मिल गए हैं और यह करना सबसे आसान लग रहा था। मैं बस यह सुनिश्चित करना चाहता था कि मैं पागल नहीं था क्योंकि इसे 6 गुना बढ़ा दिया गया है, इसलिए मैंने सोचा कि शायद लोगों को इसके साथ सफलता मिली है। ऐसा कुछ न करें जो लोगों को भी काम न करे :)। मैं बस कई अन्य दृष्टिकोणों में से एक कोशिश करूंगा। धन्यवाद। – testing123

+0

इसे कम करने में मदद: पी –

11

मैं नीचे एक इकाई श्रोता में एक वसंत सेम सुई AOP का उपयोग कर के रास्ते जाने के लिए शुरू कर दिया।

यह एक जेपीए EntityListener वर्ग में वसंत में कामयाब सेम इंजेक्षन करना संभव नहीं है: एक दिन और अनुसंधान और अलग अलग बातें की कोशिश कर के एक आधे के बाद मैं इस link जिसमें कहा गया बारे में जाना। ऐसा इसलिए है क्योंकि जेपीए श्रोता तंत्र एक स्टेटलेस वर्ग पर आधारित होना चाहिए, इसलिए विधियां प्रभावी रूप से स्थिर हैं, और गैर-संदर्भ जागरूक हैं। ... एओपी की कोई राशि आपको बचाएगी, श्रोता का प्रतिनिधित्व करने वाले 'ऑब्जेक्ट' को कुछ भी इंजेक्शन नहीं दिया जाता है, क्योंकि कार्यान्वयन वास्तव में उदाहरण नहीं बनाते हैं, लेकिन क्लास विधि का उपयोग करते हैं।

इस बिंदु पर मैं EclipseLink DescriptorEventAdapter भर में फिर से इकट्ठा हुआ और ठोकर खाई। इस जानकारी का उपयोग करके मैंने एक श्रोता वर्ग बनाया जो वर्णनकर्ता एडाप्टर को बढ़ाता है।

public class EntityListener extends DescriptorEventAdapter { 
    private String injectedValue; 

    public void setInjectedValue(String value){ 
     this.injectedValue = value; 
    } 

    @Override 
    public void aboutToInsert(DescriptorEvent event) { 
     // Do what you need here 
    } 
} 

आदेश वर्ग का उपयोग करने के मैं अपने इकाई वर्ग पर @EntityListeners एनोटेशन का इस्तेमाल किया जा सकता था। दुर्भाग्यवश, यह विधि स्प्रिंग को मेरे श्रोता के निर्माण को नियंत्रित करने की अनुमति नहीं देगी और नतीजतन निर्भरता इंजेक्शन की अनुमति नहीं होगी।इसके बजाय मैं अपने वर्ग के लिए निम्न 'init' समारोह कहा:

public void init() { 
    JpaEntityManager entityManager = null; 

    try { 
     // Create an entity manager for use in this function 
     entityManager = (JpaEntityManager) entityManagerFactory.createEntityManager(); 
     // Use the entity manager to get a ClassDescriptor for the Entity class 
     ClassDescriptor desc = 
      entityManager.getSession().getClassDescriptor(<EntityClass>.class); 
     // Add this class as a listener to the class descriptor 
     desc.getEventManager().addListener(this); 
    } finally { 
     if (entityManager != null) { 
      // Cleanup the entity manager 
      entityManager.close(); 
     } 
    } 
} 

एक छोटे से वसंत एक्सएमएल विन्यास

<!-- Define listener object --> 
<bean id="entityListener" class="EntityListener " init-method="init"> 
    <property name="injectedValue" value="Hello World"/> 
    <property name="entityManagerFactory" ref="emf"/> 
</bean> 

अब हम एक स्थिति है जहाँ वसंत एक इकाई श्रोता बनाता है जोड़े, जो कुछ भी निर्भरता के साथ यह इंजेक्शन की आवश्यकता है, और श्रोता ऑब्जेक्ट स्वयं को इकाई वर्ग के साथ पंजीकृत करता है जिस पर वह सुनना चाहता है।

मुझे आशा है कि इस मदद करता है।

8

और क्या इस समाधान के बारे में?

@MappedSuperclass 
@EntityListeners(AbstractEntityListener.class) 
public abstract class AbstractEntity { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "id") 
    private Long id; 

    @Column(name = "creation_date") 
    private Date creationDate; 

    @Column(name = "modification_date") 
    private Date modificationDate; 

} 

तो श्रोता ...

@Component 
public class AbstractEntityListener { 

    @Autowired 
    private DateTimeService dateTimeService; 

    @PreUpdate 
    public void preUpdate(AbstractEntity abstractEntity) { 
     AutowireHelper.autowire(this, this.dateTimeService); 
      abstractEntity.setModificationDate(this.dateTimeService.getCurrentDate()); 
    } 

    @PrePersist 
    public void prePersist(AbstractEntity abstractEntity) { 
     AutowireHelper.autowire(this, this.dateTimeService); 
     Date currentDate = this.dateTimeService.getCurrentDate(); 
     abstractEntity.setCreationDate(currentDate); 
     abstractEntity.setModificationDate(currentDate); 
    } 
} 

और सहायक ... मेरे लिए

/** 
    * Helper class which is able to autowire a specified class. It holds a static reference to the {@link org 
    * .springframework.context.ApplicationContext}. 
    */ 
    public final class AutowireHelper implements ApplicationContextAware { 

     private static final AutowireHelper INSTANCE = new AutowireHelper(); 
     private static ApplicationContext applicationContext; 

     private AutowireHelper() { 
     } 

     /** 
     * Tries to autowire the specified instance of the class if one of the specified beans which need to be autowired 
     * are null. 
     * 
     * @param classToAutowire the instance of the class which holds @Autowire annotations 
     * @param beansToAutowireInClass the beans which have the @Autowire annotation in the specified {#classToAutowire} 
     */ 
     public static void autowire(Object classToAutowire, Object... beansToAutowireInClass) { 
      for (Object bean : beansToAutowireInClass) { 
       if (bean == null) { 
        applicationContext.getAutowireCapableBeanFactory().autowireBean(classToAutowire); 
       } 
      } 
     } 

     @Override 
     public void setApplicationContext(final ApplicationContext applicationContext) { 
      AutowireHelper.applicationContext = applicationContext; 
     } 

     /** 
     * @return the singleton instance. 
     */ 
     public static AutowireHelper getInstance() { 
      return INSTANCE; 
     } 

    } 

काम करता है।

स्रोत: http://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/

+0

इस समाधान के साथ एक गॉचाचा है यदि EntityListener को एप्लिकेशन कॉन्टेक्स्ट के प्रारंभ में ही उपयोग किया जाता है; तो आपको यह सुनिश्चित करना होगा कि 'AutowireHelper' बीन उस कोड से पहले शुरू किया गया है जो इसका उपयोग करता है। – holmis83

+0

काम करता है, लेकिन कॉन्फ़िगरेशन xml या जावा स्प्रिंग कॉन्फ़िगरेशन में AutowireHelper को पंजीकृत करने के बाद ही: @ बीन सार्वजनिक ऑटोवायरहेल्पर ऑटोवायरहेल्पर() { वापसी AutowireHelper.getInstance(); } – ashes

7

यह वास्तव में एक पुराने सवाल है, लेकिन मैं वैकल्पिक समाधान:

public class MyEntityListener { 
    @Autowired 
    private ApplicationEventPublisher publisher; 

    @PostPersist 
    public void postPersist(MyEntity target) { 
     SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 

     publisher.publishEvent(new OnCreatedEvent<>(this, target)); 
    } 

    @PostUpdate 
    public void postUpdate(MyEntity target) { 
     SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 

     publisher.publishEvent(new OnUpdatedEvent<>(this, target)); 
    } 

    @PostRemove 
    public void postDelete(MyEntity target) { 
     SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 

     publisher.publishEvent(new OnDeletedEvent<>(this, target)); 
    } 
} 

शायद नहीं सबसे अच्छा एक लेकिन स्थैतिक चर की तुलना में बेहतर w/ओ AOP + बुनाई।

+0

और xml का उपयोग किए बिना उस श्रोता को वास्तविक इकाई में कैसे संलग्न करें ?? – Antoniossss

+0

संबंधित इकाई पर '@ एंटीलिटीस्टर्स (MyEntityListener.class) 'जोड़ें। –

+0

नहीं कर सकता - मॉडल अलग जार में है। मेरा मतलब है कि रनटाइम पर एक्सएमएल के बिना ऐसा कैसे करना है। – Antoniossss

3

मैं बाहर का परीक्षण दृष्टिकोण https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/ में सुझाव दिया और काम किया। बहुत साफ नहीं है लेकिन नौकरी करता है। मेरे लिए थोड़ा संशोधित AutowireHelper वर्ग इस तरह देखा:

import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 
import org.springframework.stereotype.Component; 

@Component 
public class AutowireHelper implements ApplicationContextAware { 

    private static ApplicationContext applicationContext; 

    private AutowireHelper() { 
    } 

    public static void autowire(Object classToAutowire) { 
     AutowireHelper.applicationContext.getAutowireCapableBeanFactory().autowireBean(classToAutowire); 
    } 

    @Override 
    public void setApplicationContext(final ApplicationContext applicationContext) { 
     AutowireHelper.applicationContext = applicationContext; 
    } 
} 

तो इस तरह इकाई श्रोता से कहा जाता है:

public class MyEntityAccessListener { 

    @Autowired 
    private MyService myService; 


    @PostLoad 
    public void postLoad(Object target) { 

     AutowireHelper.autowire(this); 

     myService.doThings(); 
     ... 
    } 

    public void setMyService(MyService myService) { 
     this.myService = myService; 
    } 
}