2017-09-21 5 views
0

Ich habe eine API in Java Sprint, die täglich eine Aufgabe ausführen muss, um einige Daten von einem externen System zu importieren, das einen TXT in einem FTP-Server generiert. Das Problem, das ich habe, ist, dass die Autowired-Felder nicht autowired werden .... Ich meine, sie sind null.Autowired mit TimerTask funktioniert nicht

Ich verwende @PostConstruct, um bei jedem Start der App eine Aufgabe auszuführen, sodass ich die Aktion mit einem Timer planen kann.

Versuch 1

Hier ist der Code (zuerst die PostContruct Methode)

@Override 
    @PostConstruct 
    @Transactional 
    public Response importdata(){ 
     Response response = new Response(); 
     try { 
      System.out.println("*** Setting Import ****"); 
      Calendar calendar = Calendar.getInstance(); 
      calendar.set(Calendar.HOUR_OF_DAY, 21); 
      calendar.set(Calendar.MINUTE, 5); 
      calendar.set(Calendar.SECOND, 0); 
      calendar.set(Calendar.MILLISECOND, 0); 

      Timer time = new Timer(); // Instantiate Timer Object 
      time.schedule(new ImportServiceImpl(), calendar.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      response.setCode(CodeList.EXCEPTION); 
      response.setSuccess(false); 
     } 
     return response; 
    } 

Also hier bin ich um 21.05 die Funktion Tagesplanung.

Hier haben Sie ImportServiceImpl

@Component 
public class ImportServiceImpl extends TimerTask implements ImportService{ 

    @Autowired 
    InvoiceDao invoiceDao; 

    @Autowired 
    ClientDao clientDao; 

    @Override 
    @Transactional 
    public void run() { 
     System.out.println("*** Running **** " + new Date()); 
     startImport(); 
    } 

    @Override 
    @Transactional 
    public void startImport() { 
     Path dir = Paths.get(ResourcesLocation.IMPORT_ROUTE); 
     Boolean success = true; 
     try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) { 
      for (Path entry : stream) { 
       if (!Files.isDirectory(entry)) { 
        BufferedReader br = new BufferedReader(
          new InputStreamReader(new FileInputStream(ResourcesLocation.IMPORT_ROUTE + entry.getFileName().toString()))); 
        System.out.println("*** Importing file **** " + ResourcesLocation.IMPORT_ROUTE + entry.getFileName().toString()); 
        try { 
         String line; 
         int i = 0; 
         while ((line = br.readLine()) != null) { 

          final String[] parts = line.split("\\|"); 
          System.out.println("Line: " + i++ + " Text: " + line); 
          System.out.println("Factura: " + parts[1]); 
          Client client = (Client) this.clientDao.get(parts[0]); 
          String invoiceNumber = this.generateInvoiceNumber(parts[1].substring(1).replace("-", "")); 
          Invoice inv = (Invoice) this.invoiceDao.getByNumber(invoiceNumber); 
          if(inv == null){ 
           inv = new Invoice(); 
           inv.setClient(client); 
           inv.setNumber(invoiceNumber); 
           inv.setDate(this.convertDate(parts[2])); 
           inv.setTotal(this.convertFloat(parts[3])); 
           inv = (Invoice) this.invoiceDao.addOrUpdate(inv); 
          } 
         } 
        } 
        catch (Exception e) { 
         e.printStackTrace(); 
         success = false; 
        } 
        finally { 
         try { 
          br.close(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
         if(success){ 
          try { 
           Files.delete(entry); 
          } catch (IOException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
         } 
        } 
       } 
      } 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
    } 

Das Problem hier ist, dass this.clientDao autowired werden sollte, aber es ist null .... Also habe ich versucht

if(this.clientDao == null) 
    this.clientDao = new ClientDaoImpl(); 

Aber dann zu tun, in der Get-Methode in ClientDaoImpl habe ich

@SuppressWarnings("unchecked") 
    public Object get(String name) throws Exception 
    { 
     Query q = sessionFactory.getCurrentSession() 
       .createQuery("from " + this.entity + " WHERE name = '" + name + "'"); 
     return q.uniqueResult(); 
    } 

Und dort sessionFac Tory war null, da es nicht autowired wurde .. Und ich glaube nicht, dass die Lösung jede Klasse die Initialisierung manuell ... zu halten ist

attemp 2

Dann habe ich versucht stattdessen die Klasse ImportServiceImpl Autowired der Initialisierung manuell und änderte meinen Code mit:

@Autowired 
    ImportService importService; 

und

time.schedule(this.importService, calendar.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); 

Aber es bekomme ich einen Fehler, weil die this.importService nicht ist ImportServ iceImpl, es ist ImportService, welches die Schnittstelle ist und die Schnittstelle TimerTask nicht erweitern kann.

3 Versuch

Ändern der Autowired Klasse, um die Umsetzung und nicht die Schnittstelle autowired. So:

@Autowired 
    ImportServiceImpl importService; 

So bekomme ich folgende Fehlermeldung:

java.lang.IllegalArgumentException: Can not set com.app.services.ImportServiceImpl field com.app.services.InvoiceServiceImpl.importService to com.sun.proxy.$Proxy184 

Ich habe die Antworten in Why is my Spring @Autowired field null?

Aber die manuelle Lösung funktioniert nicht wie der Kontext nie gefassten wird. Auch habe ich versucht mit der @Configure Annotation, die hier auch vorgeschlagen wurde und oder ich weiß nicht, wie man es benutzt oder es funktioniert nicht.

das Beispiel zu vereinfachen: ich eine Klasse InvoiceServiceImpl haben, die ein Verfahren import mit dem Vermerk @PostConstruct hat, wird es so nach dem App Start aufgerufen (das Teil in Ordnung ist) die import Methode, eine Timertask für die Klasse ImportServiceImpl planen (So ​​weit, ist es gut).Aber dann, wenn es der richtige Zeitpunkt ist, wird die Methode ausgeführt, aber die @ Autowired-Eigenschaften innerhalb der Methode in der Timertask-Klasse sind null.

Antwort

1

Aktualisiert

Ich organisierte eine kleine Änderung, wie Code vorzuschlagen haben wird.

Zuerst ist ImportService definiert.

public interface ImportService { 
    public void startImport(); 
} 

Und die damit verbundene Implementierung.

@Service 
public class ImportServiceImpl implements ImportService { 

    @Autowired 
    private InvoiceDao invoiceDao; 

    @Autowired 
    private ClientDao clientDao; 

    @Override 
    @Transactional 
    public void startImport() { 
     // Process... 
    } 

Dann haben Sie Ihre TimerTask Implementierung.

@Component 
public class ImportTimerTask extends TimerTask { 

    @Autowired 
    private ImportService importService; 

    @Override 
    public void run() { 
     importService.startImport(); 
    } 
} 

Und schließlich haben Sie die @PostConstruct Methode in einer Klasse.

@Autowired 
private ImportTimerTask importTimerTask; 

@PostConstruct 
@Transactional 
public void importData() { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.set(Calendar.HOUR_OF_DAY, 9); 
    calendar.set(Calendar.MINUTE, 2); 
    calendar.set(Calendar.SECOND, 0); 
    calendar.set(Calendar.MILLISECOND, 0); 
    Timer time = new Timer(); 
    time.schedule(importTimerTask, calendar.getTime(), 
      TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); 
} 

Mit einer solchen Implementierung meine einfache Tests waren in Ordnung, invoiceDao und cliendDao wurden erfolgreich autowired.


können Sie versuchen, @EnableAspectJAutoProxy(proxyTargetClass=true) in einer @Configuration Klasse, um das Hinzufügen Versuch 3.

Weitere Referenz zu implementieren Sie here finden.

+0

Ich habe das meinem WebConfig aber es hat nicht funktioniert: @ EnableWebMvc @ EnableAspectJAutoProxy (proxyTargetClass = true) public class WebConfig erweitert WebMvcConfigurerAdapter {.. Jetzt @ Konfiguration Ich erhalte $ Proxy174 Fehler (Ich weiß nicht, ob die Nummer zählt) – Faabass

+0

Aktualisierte Antwort mit einem Code Änderungsvorschlag. Ich hoffe, das hilft. – lzagkaretos

+1

Oh Mann! du rettest mein Leben! Es funktioniert wie ein Champion! – Faabass

Verwandte Themen