2017-08-26 9 views
0

Ich kämpfe für 2 Tage lang versucht, dies zu lösen, und ich weiß nicht, was ich noch tun kann. Mein System funktionierte ziemlich gut, bis ich @Audit in die Entitäten einschloss. Natürlich habe ich Hibernate Envers in die .pom-Datei aufgenommen.Audit + Spring-Boot-Daten-JPA + Hibernate + JPA 2 Transaktions Ausnahme

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-envers</artifactId> 
</dependency> 

Ich habe bereits versucht, diese Beiträge:

Hibernare envers Audit with Spring data JPA and Spring Boot

spring-data-envers Hibernate java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionImplementor.getTransactionCoordinator

Hibernate-envers throwing exception when Deleting entity with a collection using CrudRepository

Aber leider ohne Erfolg überhaupt

:(

Ich überprüfte mein maven repository und ich bemerkte, dass es Hibernate 5.0.12.Final Versionen von Hibernate-Core, Hibernate-Entitymanager und Hibernate-Envers verwendet, egal welche Version ich in der .pom-Datei festgelegt.

Hier ist meine .pom Abhängigkeiten der Datei:

<dependencies> 
    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-jpa</artifactId> 
    </dependency> 
    <dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-envers</artifactId> 
    </dependency> 
    <dependency> 
    <groupId>org.hibernate.javax.persistence</groupId> 
    <artifactId>hibernate-jpa-2.1-api</artifactId> 
    <version>1.0.0.Final</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-jersey</artifactId> 
    </dependency> 

    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 

    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web-services</artifactId> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-devtools</artifactId> 
    <scope>runtime</scope> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-web</artifactId> 
    <version>4.2.3.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-config</artifactId> 
    <version>4.2.3.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>io.jsonwebtoken</groupId> 
    <artifactId>jjwt</artifactId> 
    <version>0.7.0</version> 
    </dependency> 
    <dependency> 
    <groupId>org.postgresql</groupId> 
    <artifactId>postgresql</artifactId> 
    <version>42.1.3</version> 
    </dependency> 
    <dependency> 
    <groupId>com.zaxxer</groupId> 
    <artifactId>HikariCP</artifactId> 
    <version>2.6.1</version><!--$NO-MVN-MAN-VER$--> 
    </dependency> 

    <dependency> 
    <groupId>io.swagger</groupId> 
    <artifactId>swagger-core</artifactId> 
    <version>1.5.13</version> 
    </dependency> 

    <dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-test</artifactId> 
    <scope>test</scope> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework.restdocs</groupId> 
    <artifactId>spring-restdocs-mockmvc</artifactId> 
    <scope>test</scope> 
    </dependency> 

    <dependency> 
    <groupId>org.apache.poi</groupId> 
    <artifactId>poi-ooxml</artifactId> 
    <version>3.16</version> 
    </dependency> 
</dependencies> 

Hier ist Listener Klasse

public class BRAuditEnversListener implements RevisionListener { 
    protected static final Logger log = Logger.getLogger("com.zerofila.web"); 

    @Autowired 
    private UserService service; 

    @Override 
    public void newRevision(Object revisionEntity) {   
    BRAuditRevisionEntity customRevisionEntity = (BRAuditRevisionEntity) revisionEntity; 
    customRevisionEntity.setUsername(service.getAuthenticatedUser().getEmail()); 
    } 
} 

Revinfo Klasse:

@Entity 
@Table(name = "revinfo") 
@RevisionEntity(BRAuditEnversListener.class) 
public class BRAuditRevisionEntity implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @RevisionNumber 
    private int id; 
    @RevisionTimestamp 
    private long timestamp; 
    private String username; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    public int getId() { 
    return id; 
    } 

    public void setId(int id) { 
    this.id = id; 
    } 

    @Transient 
    public Date getRevisionDate() { 
    return new Date(timestamp); 
    } 

    public long getTimestamp() { 
    return timestamp; 
    } 

    public void setTimestamp(long timestamp) { 
    this.timestamp = timestamp; 
    } 

    @Override 
    public boolean equals(Object o) { 
    if (this == o) { 
     return true; 
    } 
    if (!(o instanceof DefaultRevisionEntity)) { 
     return false; 
    } 

    DefaultRevisionEntity that = (DefaultRevisionEntity) o; 

    if (id != that.getId()) { 
     return false; 
    } 
    if (timestamp != that.getTimestamp()) { 
     return false; 
    } 

    return true; 
    } 

    @Override 
    public int hashCode() { 
    int result; 
    result = id; 
    result = 31 * result + (int) (timestamp^(timestamp >>> 32)); 
    return result; 
    } 

    @Override 
    public String toString() { 
    return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")"; 
    } 

    public String getUsername() { 
    return username; 
    } 

    public void setUsername(String username) { 
    this.username = username; 
    } 
} 

Web-Service-Endpunkt, die das Insert-Methode aufruft:

@Override 
@RequestMapping(value = "/create", method = RequestMethod.POST) 
public ResponseEntity<Local> create(@ApiParam(value = "Local json stream resource", required = true) @Valid @RequestBody Local local) { 
    Local created = service.insert(local); 

    if (null == created) 
     return new ResponseEntity<>(HttpStatus.NOT_MODIFIED); 

    return new ResponseEntity<Local>(created, HttpStatus.CREATED); 
} 

Hier ist es ein Verfahren ist, das die Ausnahme wirft:

@Transactional 
@Override 
public Local insert(Local local) { 
    return repository.save(local); 
} 

Und schließlich die Ausnahme (ziemlich kurz, btw):

2017-08-26 20:18:52.006 ERROR 2784 --- [nio-8080-exec-4] org.hibernate.AssertionFailure   : HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.NullPointerException 
2017-08-26 20:18:52.009 WARN 2784 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction 

Muss ich etwas Besonderes konfigurieren müssen? Vielleicht eine Anmerkung hinzufügen? Irgendeine Idee darüber, was ich tun kann?

+0

Es ist nicht klar, wie eine Instanz von 'Local' löst eine Einsparung Prüfereignis (was dann zu der genannten Ausnahme führt). Außerdem ist die POM-Datei für ein korrektes Spring-Boot-Projekt viel zu kompliziert (zum Beispiel, warum Startdaten JPA- und JPA-API enthalten sind; sie werden bereits vom Spring-Boot-Starter importiert).Sie sollten versuchen, die Überwachung zuerst mit einem Spring-Boot-Projektprojekt zu implementieren (erstellen Sie eins unter http://start.spring.io), ohne irgendwelche Abhängigkeiten einzuführen, die für das Auditing irrelevant sind. Wenn die Dinge funktionieren, fügen Sie nach und nach weitere Teile hinzu. – manish

+0

Danke @manish, ich werde alle diese überprüfen. Was ist seltsam ist, dass (wie ich schon sagte) "Mein System arbeitete ziemlich gut bis zu dem Moment, als ich @Audit in den Entitäten enthalten." und die Winterschlaf-Enver als Abhängigkeit natürlich. Bottom line, empfehlen Sie mir, diese Einträge in meiner .pom-Datei auszuschließen: ' Spring-Boot-Starter-Daten-Jpa' und ' Hibernate-Jpa-2.1-Api'? Übrigens habe ich die Methode hinzugefügt, die den Einschub in der Frage aufruft. Danke –

+0

Ich würde empfehlen, ein Beispielprojekt mit nur 'Spring-Boot-Starter' und 'Hibernate-Envers' Abhängigkeiten zu erstellen und Audit-Anforderungen damit zu testen. – manish

Antwort

0

Nach einer langen Zeit (ca. 3 Tage) versuchen und testen und analysieren alle die Quelle, fand ich den Fehler und folglich die Lösung.

Der Fehler, weil dieses Eintrags auftreten wurde:

@Autowired 
private UserService service; 

Aus irgendeinem Grund wurde die service.getAuthenticatedUser() null zurückkehrt und dann wurde die Ausnahme geworfen.

war meine Lösung die authentifizierte Benutzer direkt von SecurityContextHolder, wie diese zu bekommen:

public class BRAuditEnversListener implements RevisionListener { 

    @Override 
    public void newRevision(Object revisionEntity) {   
     BRAuditRevisionEntity customRevisionEntity = (BRAuditRevisionEntity) revisionEntity; 
     Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
     customRevisionEntity.setUsername((String)authentication.getPrincipal()); 
    } 
} 

Nun, die Dinge funktionieren :)