java - Statically finding methods that need @Transactional but don't have it -
in order avoid database connection leaks, it's possible configure c3p0 let know when occur, , point problem code:
<property name="unreturnedconnectiontimeout" value="900"/> <!-- seconds --> <property name="debugunreturnedconnectionstacktraces" value="true"/>
it'd better catch these before ever deployed. is, catch them statically @ build time. seems possible 1) identify classes dao-type classes, either annotated such or via hbm file, , 2) trace call trees upward , flag methods not marked @transactional. if there false positives, that'd useful tool eliminate issue. ides such intellij , eclipse know how find method's callers.
is there opensource tool this? if didn't first step, it's easy enough identify daos manually. it's second part benefit automated solution.
i faced similar problem in spring application, , wrote bean processer ran @ application startup, , examined each bean after initialized. it's not compile-time solution, assuming run application somewhere before production, you'll have opportunity find methods lacking annotation in question.
it looked classes @service annotation, iterated on interfaces implemented class, , inspected each interface's methods. looked methods either didn't have method-level security defined, or had custom @unsecured
annotation, indicating had discovered method lacked security determined didn't need security. methods lacked security and @unsecured
annotation logged.
the following code worked @ 1 point, used older version of spring. don't know if work spring 3.x, if not, similar approach should still work. might need adjust inspection logic suite needs (e.g. classes different class-level annotation, inspect methods on class instead of methods in interfaces implemented class, etc). note approach didn't try traverse call trees, you'd more false positives (i.e. not service methods end calling dao methods).
public class unsecuredservicemethodprocessor implements beanpostprocessor { private static final logger logger = logmanager.getlogger(unsecuredservicemethodprocessor.class); private final methodsecurityinterceptor interceptor; public unsecuredservicemethodprocessor(methodsecurityinterceptor interceptor) { this.interceptor = interceptor; } @override public object postprocessafterinitialization(object bean, string beanname) throws beansexception { class<?> beanclass = bean.getclass(); if (logger.isinfoenabled()) { logger.info("checking bean " + beanname + " of type " + beanclass.getname()); } (class<?> interfaceclass: beanclass.getinterfaces()) { checkclass(beanclass, interfaceclass); } return bean; } /** * @param beanclass * @param interfaceclass */ private void checkclass(class<?> beanclass, class<?> interfaceclass) { if (interfaceclass.isannotationpresent(service.class)) { if (logger.isdebugenabled()) { logger.debug("found service implementation: " + interfaceclass + " on " + beanclass); } (method method: interfaceclass.getmethods()) { if (!method.isannotationpresent(unsecured.class)) { if (logger.isdebugenabled()) { logger.debug("checking " + method.getname()); } methodsecuritymetadatasource msms = interceptor.getsecuritymetadatasource(); collection<configattribute> atts = msms.getattributes(method, interfaceclass); if (atts == null || atts.size() == 0) { logger.warn("unsecured method: " + method.getdeclaringclass().getname() + "." + method.getname()); } } } } } @override public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception { return bean; } }
you'll need either explicitly define bean of type in application context, or add @component
class-level annotation , scan it.
Comments
Post a Comment