java - Spring JPA postProcessBeforeDestruction being called on non-entity -
it's bit complex describe environment i'll try best.
i'm seeing no functional error, i'm concerned error see in logs after spring context being closed (it's batch application executes , closes) it's triggering jpa destruction on object has nothing jpa.
java.lang.unsupportedoperationexception: method org.springframework.web.client.restoperations.hashcode not implemented. @ net.mycompany.authenticationclient.restoperationswithauthentication.invoke(restoperationswithauthentication.java:29) @ com.sun.proxy.$proxy25.hashcode(unknown source) @ java.util.concurrent.concurrenthashmap.hash(concurrenthashmap.java:333) @ java.util.concurrent.concurrenthashmap.remove(concurrenthashmap.java:1175) @ org.springframework.orm.jpa.support.persistenceannotationbeanpostprocessor.postprocessbeforedestruction(persistenceannotationbeanpostprocessor.java:358) @ org.springframework.beans.factory.support.disposablebeanadapter.destroy(disposablebeanadapter.java:238) @ org.springframework.beans.factory.support.defaultsingletonbeanregistry.destroybean(defaultsingletonbeanregistry.java:540) @ org.springframework.beans.factory.support.defaultsingletonbeanregistry.destroysingleton(defaultsingletonbeanregistry.java:516) @ org.springframework.beans.factory.support.defaultlistablebeanfactory.destroysingleton(defaultlistablebeanfactory.java:824) @ org.springframework.beans.factory.support.defaultsingletonbeanregistry.destroysingletons(defaultsingletonbeanregistry.java:485) @ org.springframework.context.support.abstractapplicationcontext.destroybeans(abstractapplicationcontext.java:921) @ org.springframework.context.support.abstractapplicationcontext.doclose(abstractapplicationcontext.java:895) @ org.springframework.context.support.abstractapplicationcontext.close(abstractapplicationcontext.java:841)
there jpa configuration it's listening on different package:
<bean id="dashboard_entity_manager_factory" class="org.springframework.orm.jpa.localcontainerentitymanagerfactorybean"> <property name="packagestoscan" value="net.mycompany.dashboard.domain" /> <property name="persistenceunitname" value="dashboard"/> <property name="datasource" ref="dashboard_connection_pool" /> <property name="jpavendoradapter"> <bean class="org.springframework.orm.jpa.vendor.hibernatejpavendoradapter"> <property name="database" value="mysql" /> <property name="showsql" value="true" /> </bean> </property> </bean>
the invokation handler:
public class restoperationswithauthentication implements invocationhandler { protected restoperations restclient; protected authenticationclient authclient; protected boolean authenticated; public restoperationswithauthentication(restoperations restclient, authenticationclient authclient) { this.restclient = restclient; this.authclient = authclient; this.authenticated = false; } @override public object invoke(object proxy, method method, object[] arguments) throws throwable { if (arguments == null || !(arguments[0] instanceof string)) { throw new unsupportedoperationexception("method " + restoperations.class.getcanonicalname() + "." + method.getname() + " not implemented."); } string url = arguments[0].tostring(); if (!authenticated) { authclient.authenticate(null); authenticated = true; } authenticationurl<string> authurl = authclient.addauthparameters(url); arguments[0] = authurl.geturl(); try { return invoke(method, arguments); } catch (httpclienterrorexception e) { if (e.getstatuscode().equals(httpstatus.forbidden)) { authclient.authenticate(authurl.getsessiontoken()); arguments[0] = authclient.addauthparameters(url).geturl(); return invoke(method, arguments); } throw e; } } protected object invoke(method method, object[] arguments) throws throwable { try { return method.invoke(restclient, arguments); } catch (invocationtargetexception e) { throw e.getcause(); } }
}
and creation of object matters is
<bean id="auth_http_client" class="org.springframework.web.client.restoperations" factory-bean="auth_http_client_factory" factory-method="createrestclientwithauthentication" />
which decorator on resttemplate introducing custom authentication layer on apis. tried declaring class resttemplate there no difference.
now in cases, there no functional issue, things work expected, concerned why spring jpa postprocessor being hooked random bean. edge case beats me... can't seem follow what's going on.
spring version 4.0.2. tried older versions, doesn't seem make difference.
my question why happening , how can avoid it?
note, upon debugging have found seems defined beans being included in concurrenthashmap. perhaps issue mixing xml annotations?
i have in 1 of xmls imported context:
<tx:annotation-driven transaction-manager="dashboard_transaction_manager" proxy-target-class="true"/> <context:annotation-config/>
but beans being called in persistence post processor not annotated transactional.
take @ javadoc of persistenceannotationbeanpostprocessor
or pabpp
, , @ source code. contains concurrenthashmap
called extendedentitymanagerstoclose
. keys of map beans may have had entitymanager
or entitymanagerfactory
injected because of persistenceunit
or persistencecontext
annotations.
now pabpp
implements destructionawarebeanpostprocessor
, postprocessbeforedestruction()
method called during container destruction every bean being destroyed. implementation of method calls remove()
on map, specifying bean being destroyed key, in case there's associated entitymanager*
. calling concurrenthashmap.remove()
in turn calls hashcode()
on key, i.e. on every bean.
it blows because when hashcode()
called via restoperationswithauthentication.invoke()
violates guard clause expects method arguments.
Comments
Post a Comment