2016-07-31 23 views
1

私の豆のメソッドからNonUniqueResultExceptionをキャッチするのに問題があります。NonUniqueResultExceptionがキャッチされていません

ここにその方法があります。これは、@Stateful beanの内部にあります。簡単に言えば

public Field findByTitle(String title) { 
    if (title == null) 
     return null; 

    try { 
     return entityManager 
       .createQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class) 
       .setParameter(1, title) 
       .getSingleResult(); 
    } catch (NoResultException e) { 
     return null; 
    } 
} 

、私は、このメソッドを呼び出して別のBeanから未チェックNonUniqueResultExceptionをキャッチしたいです。ここで

は呼び出し豆ののtry/catchです:

try { 
    Field field = fieldService.findByTitle(title); 
} catch (NonUniqueResultException e) { 
    LogManager.logError("Oh no!"); 
} 

私の予想は "!ああ、いや" ということですコンソールに印刷されます。代わりに、NonUniqueResultExceptionのスタックトレース全体が表示されます。キャッチコールは決して触れられません!

スタックトレース:(この行を参照:.getSingleResult();

03:39:07,228 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-93) javax.ejb.EJBException: javax.persistence.NonUniqueResultException: result returns more than one elements 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:187) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:277) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:327) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) 
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636) 
    at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) 
    at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195) 
    at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73) 
    at me.mitcht.myapp.core.entities.services.FieldService$$$view157.findByTitle(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:436) 
    at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:127) 
    at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) 
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100) 
    at me.mitcht.myapp.core.entities.services.FieldService$Proxy$_$$_Weld$EnterpriseProxy$.findByTitle(Unknown Source) 
    at me.mitcht.myapp.web.validators.UniqueFieldValidator.validate(UniqueFieldValidator.java:39) 
    at javax.faces.component.UIInput.validateValue(UIInput.java:1164) 
    at javax.faces.component.UIInput.validate(UIInput.java:982) 
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1248) 
    at javax.faces.component.UIInput.processValidators(UIInput.java:712) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261) 
    at javax.faces.component.UIForm.processValidators(UIForm.java:253) 
    at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:575) 
    at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689) 
    at javax.faces.component.UIForm.visitTree(UIForm.java:371) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700) 
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403) 
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266) 
    at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57) 
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219) 
    at org.omnifaces.context.OmniPartialViewContext.processPartial(OmniPartialViewContext.java:144) 
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193) 
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658) 
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:81) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:265) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:200) 
    at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:193) 
    at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:106) 
    at me.mitcht.myapp.web.filters.TenantFilter.doFilter(TenantFilter.java:73) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) 
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174) 
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) 
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.persistence.NonUniqueResultException: result returns more than one elements 
    at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:539) 
    at me.mitcht.myapp.core.entities.services.FieldService.findByTitle(FieldService.java:30) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93) 
    at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.jpa.interceptor.SFSBInvocationInterceptor.processInvocation(SFSBInvocationInterceptor.java:57) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.stateful.StatefulSessionSynchronizationInterceptor.processInvocation(StatefulSessionSynchronizationInterceptor.java:125) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64) 
    at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.stateful.StatefulComponentInstanceInterceptor.processInvocation(StatefulComponentInstanceInterceptor.java:65) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275) 
    ... 112 more 

私が間違って何をしているのですか?

更新:再度原因をスローしました。同じ結果。

public Field findByTitle(String title) { 
    if (title == null) 
     return null; 

    try { 
     return entityManager 
       .createQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class) 
       .setParameter(1, title) 
       .getSingleResult(); 
    } catch (NoResultException e) { 
     return null; 
    } catch (NonUniqueResultException e) { 
     throw e; 
    } 
} 

更新:これは動作しています。しかし、私はそれがどのように動作するようにしたいのですか?

try { 
    Field field = fieldService.findByTitle(title); 
} catch (EJBException e) { 
    if (e.getCause() instanceof NonUniqueResultException) { 
     LogManager.logInfo("Oh no!"); 
    } 
    return; 
} 
+0

適切にフォーマットされたスタックトレース(または関連する部分)を用意してください。アイデアはありますが、スタックトレースを読み取って検証する必要があります。 – MWiesner

+0

@MWiesner Done。トレースの上部が必要な場合はお知らせください。私は「原因」セクションのみを含んでいました。 –

+0

ところで、明らかに、メソッドシグネチャは 'public Collection findByTitle(String title)'でなければなりません。ここでトリガーするクエリは複数の結果を返す傾向があるため、私にとっては論理になります。したがって、このメソッドはコレクションを返す必要があります。 ( "title"にユニーク制約がない場合) – MWiesner

答えて

2

@Stateful注釈付きコンテナ管理Beanから呼び出された場合、EJBExceptionが返されます(Dmitry Ginzburgの答えに記載されているように)。次のように

しかし、問題のより一貫した方法(溶液)メソッドのシグネチャと実装を変更することであろう。

public List<Field> findByTitle(String title) { 
    if (title == null) 
     return null; 

    try { 
     TypedQuery<Field> query = entityManager 
       .createTypedQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class); 
     query.setParameter(1, title) 
     return query.getResultList(); 
    } catch (NoResultException e) { 
     return null; 
    } 
} 

誘発/例外処理を受け入れることはほとんどない有効なアプローチではありません。あなたが達成しようとしていることの状況を反映して、適切に設計されたインターフェイスを常に探してください。

+0

私はあなたとドミトリーの時間がこれで私を助けてくれてありがとう。本当にありがとう!! –

+1

ようこそ。私はそれを解決するドミトリーの方法はそれ自体が間違っていないことを追加したいと思います。これは、その永続化サービスのインタフェースに対する要件によって異なります。個人的に、私は不要な接着剤コードよりも良いデザインを好む。 – MWiesner

0

あなたは、クエリの最後に限界を追加することによってそれを修正しようとすることができます。

public Field findByTitle(String title) { 
    if (title == null) 
     return null; 

    try { 
     return entityManager 
       .createQuery("SELECT f FROM Field f WHERE f.title = ?1 LIMIT 1,1", Field.class) 
       .setParameter(1, title) 
       .getSingleResult(); 
    } catch (NoResultException e) { 
     return null; 
    } 
} 
+1

残念ながら、JPQLはクエリ内で 'LIMIT'をサポートしていません。ただし、 '.setMaxResults(1)'を追加すると、データベース内で一致する複数の行がある場合に例外がスローされません。私はまだこれがキャッチされていない理由を知りたいです。 –

+1

これは有効な答えではありませんが、問題の回避策です。 – MWiesner

0

あなたはそれをキャッチして、原因を再スローする必要があるので、実際にスローされる例外は、javax.ejb.EJBException次のとおりです。

try { 
    .... 
} catch (EJBException ex) { 
    if (ex.getCause() instanceof NonUniqueResultException) { 
     throw (NonUniqueResultException)ex.getCause(); 
    } 
} 
+0

は動作しません - 問題の原因を抱えている – MWiesner

+0

実際には、コードが1つの値だけを返すと仮定した場合、複数の値を見つけたら例外をスローする必要があります。 –

+0

あなたは正しいです - それ自体が - しかし、間違って設計された持続層のインターフェースにパッチを当てるような接着剤コードを受け入れることは本当に悪い設計です。当然のことながら、彼のデータベースは 'title'に複数の一意の値を与えることができます。 – MWiesner

0

私はプロキシとしてBeanにアクセスしていますので、それは、判明したように、実際の例外はスローされますjavax.ejb.EJBExceptionです。スタックトレースからこの行を参照してください。

javax.ejb.EJBException: javax.persistence.NonUniqueResultException: result returns more than one elements 

ので、(醜い)溶液をEJBExceptionではなくNonUniqueResultExceptionをキャッチし、それは私が期待するものであることを確認し、原因を確認することです:

try { 
    Field field = fieldService.findByTitle(title); 
} catch (EJBException e) { 
    if (e.getCause() instanceof NonUniqueResultException) { 
     LogManager.logInfo("Oh no!"); 
    } 
    return; 
} 

これはうまくいきますが、ひどいデザインだと言えます。

したがって、MWiesnerの提案された解決策を使用して、ただ1つの結果ではなくCollectionの結果を返すことを選択しました。この方法で、私は単にコレクションのサイズを確認できます。 1より大きい場合、明らかに結果は一意ではありません。

+0

追加のヒント:(ちょうど)サイズを確認する場合は、永続性サービスインターフェイスに別のメソッドを追加します。 'int getFieldCount(String title)'を呼び出し、与えられた 'title'に対して複数の' Field'タプルが存在するかどうかをチェックするネイティブの "SELECT count(...)..."クエリでそれを実装します。理由:パフォーマンス面ではるかに優れたオブジェクト(データ)はDBからフェッチされません(特に 'Field'のインスタンスが返される場合)。 – MWiesner

+1

@MWiesnerそれは素晴らしい考えです。もう一度ありがとう:) –

関連する問題