2017-02-18 13 views
1

春のバックエンドに本当に厄介なStackOverflowExceptionがありました。これは簡単には解決されません。私は本当にここでいくつかの助けを見つけることを望む。spring-data-jpaアプリでStackOverflowExceptionが発生しました。AuditorAware

私のバックエンドの仕事のほとんどの部分。私はモデルのために私のRESTインターフェイスを照会することができます、彼らはうまくいけばなhateoas、GET、PUTとPOST操作が返されます。しかし1つの例外:既存のDelegationModelを更新しようとすると、無限のStackOverflowExceptionが発生します。

ここは私のDelegetionModel.javaクラスです。委譲モデルには実際に@CreatedByというアノテーションが付けられたプロパティはありません。

@Entity 
@Data 
@NoArgsConstructor 
@RequiredArgsConstructor(suppressConstructorProperties = true) //BUGFIX: https://jira.spring.io/browse/DATAREST-884 
@EntityListeners(AuditingEntityListener.class) // this is necessary so that UpdatedAt and CreatedAt are handled. 
@Table(name = "delegations") 
public class DelegationModel { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    public Long id; 

    /** Area that this delegation is in */ 
    @NonNull 
    @NotNull 
    @ManyToOne 
    public AreaModel area; 

    /** reference to delegee that delegated his vote */ 
    @NonNull 
    @NotNull 
    @ManyToOne 
    public UserModel fromUser; 

    /** reference to proxy that receives the delegation */ 
    @NonNull 
    @NotNull 
    @ManyToOne 
    public UserModel toProxy; 

    @CreatedDate 
    @NotNull 
    public Date createdAt = new Date(); 

    @LastModifiedDate 
    @NotNull 
    public Date updatedAt = new Date(); 

} 

私はSQL DBからUserModelをロードする必要AuditorAwareインタフェースを実装Spring-data-jpa docに記載されているように。このAuditorAwareインターフェイスは、@CreatedByと注釈が付けられたフィールドを持つモデルに対してのみ呼び出されると予想していました。

@Component 
public class LiquidoAuditorAware implements AuditorAware<UserModel> { 
    Logger log = LoggerFactory.getLogger(this.getClass()); // Simple Logging Facade 4 Java 

    @Autowired 
    UserRepo userRepo;  

    @Override 
    public UserModel getCurrentAuditor() { 
     Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
     if (authentication == null || !authentication.isAuthenticated()) { 
     log.warn("Cannot getCurrentAuditor. No one is currently authenticated"); 
     return null; 
     } 
     User principal = (org.springframework.security.core.userdetails.User) authentication.getPrincipal(); 
     UserModel currentlyLoggedInUser = userRepo.findByEmail(principal.getUsername()); // <<<<======= (!) 
     return currentlyLoggedInUser; 
    } catch (Exception e) { 
     log.error("Cannot getCurrentAuditor: "+e); 
     return null; 
    } 
    } 
} 

私はUserRestControllerのDelegationModelを更新しました。機能的な「スクラムユーザーストーリー」は、次のとおりです。

ユーザーとして、代理人を保管して私の代理人に投票権を転送できるようにしたいと考えています。

@RestController 
@RequestMapping("/liquido/v2/users") 
public class UserRestController { 

    [...] 

    @RequestMapping(value = "/saveProxy", method = PUT, consumes="application/json") 
    @ResponseStatus(HttpStatus.CREATED) 
    public @ResponseBody String saveProxy(
         @RequestBody Resource<DelegationModel> delegationResource, 
         //PersistentEntityResourceAssembler resourceAssembler, 
         Principal principal)   throws BindException 
    { 
    [...] 
    DelegationModel result = delegationRepo.save(existingDelegation); 
    [...] 
    } 

    [...]   

} 

私は見ることができないいくつかの理由については、このactualyは、上記AuditorAwareの実装を呼び出します。問題は今、私のLqiuidoAuditorAwareの実装が何度も何度も繰り返し呼び出されていることです。 LiquidoAuditorAware.java内のUserModelのクエリーがLiquidoAuditorAwareを再度呼び出すようです。ここでは(どのようにDBからの読み出し動作のみであるので、珍しいです。)

は、私は本当にすべてをapriciateたいすべてのコードをすることによって、このgithub repo

で見つけることができますfull ThreadDump as a Gist

ですここで助けてください。私は暗闇の中で探しています:-)

答えて

3

理由は、AuditorAware実装がJPA @PrePersist/​​コールバックから呼び出されていることです。 findByEmail(…)を呼び出すことによってクエリを発行します。これにより、ダーティー検出が再度トリガされ、フラッシングがトリガされ、コールバックが呼び出されます。

推奨される回避策は、(UserDetailsServiceが認証上のインスタンスを検索したときにそれを見ることによって)あなたは、余分なデータベースクエリを必要としないように、春のセキュリティUser実装内部UserModelのインスタンスを維持することです。

別の(あまり推奨)この問題を回避するには、フラッシュは、クエリの実行のためにトリガされないように、クエリの実行前にsetFlushMode(FlushModeType.COMMIT)を呼び出し、その後FlushModeType.AUTOにそれをリセットし、AuditorAware実装にEntityManagerを注入することであろう。

+0

すみません、ありがとうございました! AuditorAware内のクエリが問題であるという私の最初の推測がちょっとうれしいです。しかし、私は回避策を見ていませんでした。私はそれをします。 – Robert

+0

ちょうど参照のために:ちょっと前にこの非常によく似た質問が見つかりました:http://stackoverflow.com/questions/14223649/how-to-implement-auditoraware-with-spring-data-jpa-and-spring-security?rq = 1 – Robert

関連する問題