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.
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
Aktualisierte Antwort mit einem Code Änderungsvorschlag. Ich hoffe, das hilft. – lzagkaretos
Oh Mann! du rettest mein Leben! Es funktioniert wie ein Champion! – Faabass