CXF Interceptor phases being skipped for missing phase declaration - spring

Been working on this one for a bit and haven't had any luck.
I'm in the process of upgrading from Spring 3.2.9 to 4.2.6. My first step was upgrading to cxf-core 3.1.6, which I did with no issues to the app.
When upgrading all spring dependencies I am running into an issue with the interceptor setup though. Here's the basics:
Interceptor
public class MyInterceptor extends AbstractPhaseInterceptor<Message>{
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
public MyInterceptor() {
super(Phase.PRE_INVOKE);
addAfter(HolderInInterceptor.class.getName());
}
#PostConstruct
public void display() {
logger.warn(this.getPhase());
}
#Override
public void handleMessage(Message message) throws Fault {
....
cxfContext.xml
<bean id="contentInInterceptor" class="com.MyInterceptor">
</bean>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="contentInInterceptor"/>
</cxf:inInterceptors>
</cxf:bus>
as well as it being added in web.xml. When running I see the logged information showing the interceptor is created with a phase of pre-invoke (I added this to verify I'm not going crazy). But when calling the service, the PhaseInterceptor chain is skipping the interceptor for not declaring a phase:
Logs:
2016-05-31 16:08:28,208 [localhost-startStop-1] [] WARN
c.MyInterceptor - pre-invoke
2016-05-31 16:10:14,552
[http-bio-8080-exec-1] [] WARN o.a.c.p.PhaseInterceptorChain -
Skipping interceptor
com.MyInterceptor$$EnhancerBySpringCGLIB$$1afa70e1: Phase declaration
is missing.
This is intercepting a jaxws server call. Again, all I've changed that has caused the issues is updating to the latest version of Spring. It almost appears as though cxf is using a separate interceptor that was never generated from the bean.
EDIT
I believe I've found the issue, but again I'm not sure where the fix would be. Spring 4 proxy does not call the constructor twice when creating the proxy (i.e. it creates the raw bean using the constructor, but the CGLIB created proxy of the bean does not call the constructor). This causes the phase of the interceptor to be null.
I changed around my #PostContsruct on the class to confirm this:
#PostConstruct
public void display() {
logger.warn(this.getPhase());
MyInterceptor myInterceptor = (MyInterceptor) appContext.getBean("contentInInterceptor");
logger.warn("Bean phase is: " + myInterceptor.getPhase());
}
Logs show bean creation's phase versus proxy's phase:
2016-06-01 10:36:52,829 [localhost-startStop-1] [] WARN c.MyInterceptor - pre-invoke
2016-06-01 10:36:52,839 [localhost-startStop-1] [] WARN c.MyInterceptor - Bean phase is: null

Alright, I figured out a way around this for now, but it isn't the greatest implementation.
Basically what I ended up having to do was create an abstract class that implemented PhaseInterceptor and all of those implemented methods were set as abstract.
Then my interceptors extended from that class and had their own phase/id/before/after variables. It appears as though there may be an issue with Spring's bean proxy setup when variables are not available in the bean's direct class. At least that's what I'm finding in this case.
Again, not sure if it's the best solution, but this makes the interceptors work again.

You said that interceptor is intercepting jaxws server call. So my assumption is, it is outgoing call.
Phase.PRE_INVOKE is for incoming message. Use other phases like Phase.PRE_STREAM for outgoing message
For documentation of phases please see
http://cxf.apache.org/docs/interceptors.html

Related

Exception BeanFactory must be set on AnnotationAsyncExecutionAspect to access qualified executor

I created a public method with #Async and I also have a bean for that class in which this method is created. But when I am calling it , it is not behaving async and getting blocked. Then I created a executor in application-bean and used #Async(value = “executorname”), even this is not working and on every call I am getting “beanFactory must be set on AnnotationasyncExecutionAspect to access qualified executor”.
in my application bean.xml I have
there are then few executors and schedulers and I want to use one new executor.
Please tell me how to get away with this error and get async behaviour
Thanks in advance
I was experiencing exactly the same issue and find out a solution I hope works for you (https://jira.spring.io/browse/SPR-10276).
Apparently if you unabled Spring's AspectJ aspects into your project (by using aspectj-maven-plugin, for instance), Spring's Async mechanism can be placed twice in your bean, one by aspectj and other by proxy. But, since it doesn't know it, AnnotationAsyncExecutionAspect will not be injected with a BeanFactory and you will see the assertion exception you had.
To fix it, you must instruct Spring's Async mechanism to use the AspectJ support. Do this incluing this in your Application Context.
<task:annotation-driven mode="aspectj"/>
I hope I could be of any help.
For annotation based configuration you can use #EnableAsync(mode = AdviceMode.ASPECTJ)

How can I tell if Spring has loaded my #Controller?

Is there a way to tell if Spring has loaded my #Controller?
I'm requesting a URL but I'm not hitting my controller and I can't figure out why
I'm loading controllers by doing a component scan
<context:component-scan base-package="com.example.app.web"/>
Other controllers in the same package as my failing controller are working fine.
My controller code is:
#Controller
#RequestMapping(value = "/app/administration/ecosystem")
public class AppEcosystemController {
#Autowired
EcosystemManagerService ecosystemManagerService;
#RequestMapping(value = "/Foo", method = RequestMethod.GET)
public String getEcosystem() {
/* Implementation */
}
The first thing I'd like to do is to be sure that this controller is getting picked up by the component scan.
Any suggestions?
Just enable logging for your application, you can find this information at INFO level
For example in my application I have a controller named UserController.
The following log4j.properties does the trick.
log4j.rootLogger=INFO, FILE
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=../logs/rest-json.log
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
I can see in the log that RequestMappingHandlerMapping mapped my controller (scroll all the way to the right).
07:28:36,255 INFO RequestMappingHandlerMapping:182 - Mapped "{[/rest/**/users/{id}],methods=[GET],params=[],headers=[],consumes=[],produces=[text/xml || application/json],custom=[]}" onto public org..domain.User org.ramanh.controller.UserController.getUser(java.lang.String)
07:28:36,255 INFO RequestMappingHandlerMapping:182 - Mapped "{[/rest/**/users],methods=[POST],params=[],headers=[],consumes=[],produces=[text/xml || application/json],custom=[]}" onto public void org..controller.UserController.addUser(org...domain.User)
If you are still unsure I would suggest adding a method annotated with #PostConstruct.
You could easily look up the message in the log or place a break point in this method.
#PostConstruct
protected void iamAlive(){
log.info(“Hello AppEcosystemController”)
}
If you find that your controller is initialized correctly but still the url is not accessible.I would test the following
You are getting 404 error - maybe you are not pointing to the correct
url (do not forget to add the application as prefix to the url)
You are getting 404 error - Dispatcher servlet mapping in web.xml doesn't meet
the url above
You are getting 403/401 – maybe you are using
spring security and it’s blocking the url
You are getting 406 – your
content type definition is conflicting with your request
You are getting 50x – something is buggy in your code
I made an ApplicationContextDumper. Add it into application context, it will dump all beans and their dependencies in the current context and parent contexts (if any) into log file when the application context initialization finishes. It also lists the beans which aren’t referenced.
It was inspired by this answer.
You could start out with enabling debug logging for Spring as outlined here.
I'd also recommend leveraging the MVC testing support, which you'll find in the spring-test jar. Details on how to use it can be found here and here.

WebApplicationInitializer being called repeatedly

I have a Spring 3.1 based application hosted under Tomcat 7.x (latest version). The application is configured exclusively with Java (no web.xml, no Spring XML configuration). All unit tests are passing, including ones using the Spring Java configuration (#ContextConfiguration).
The problem is that when the application is deployed, the WebApplicationInitializer implementation is being called multiple times. Repeated registrations of filters and listeners causes exceptions and the application never starts.
I was not expecting WebApplicationInitializer.onStartup() to be called repeatedly and would like to eliminate that behavior if possible. If anyone has suggestions on why this might be happening, and how to stop it, I'd really appreciate it.
Update I believe the problem is external to the initialization class itself, but here it is in case I am mistaken...
public class DeploymentDescriptor implements WebApplicationInitializer {
private static final Logger LOGGER = LoggerFactory.getLogger("org.ghc.web-app-initializer");
#Override
public void onStartup (ServletContext servletContext) throws ServletException {
// This is the programmatic way of declaring filters. This allows you to order
// Filters. The order of these security filters DOES MATTER!
FilterRegistration.Dynamic mockSecurityFilter = servletContext.addFilter ("mockSecurityFilter", "org.ghc.security.MockSecurityFilter");
mockSecurityFilter.addMappingForUrlPatterns (EnumSet.of (REQUEST), true, "/*");
FilterRegistration.Dynamic siteMinderSecurityFilter = servletContext.addFilter ("siteMinderSecurityFilter", "org.ghc.security.SiteMinderSecurityFilter");
siteMinderSecurityFilter.addMappingForUrlPatterns (EnumSet.of (REQUEST), true, "/*");
FilterRegistration.Dynamic userDetailsStoreFilter = servletContext.addFilter ("userDetailsStoreFilter", "org.ghc.security.UserDetailsStoreFilter");
userDetailsStoreFilter.addMappingForUrlPatterns (EnumSet.of (REQUEST), true, "/*");
// Static resource handling using "default" servlet
servletContext.getServletRegistration ("default").addMapping ("*.js", "*.css", "*.jpg", "*.gif", "*.png");
// Map jspf files to jsp servlet
servletContext.getServletRegistration ("jsp").addMapping ("*.jspf");
// Spin up the Spring 3.1 class that can scan a package tree for classes
// annotated with #Configuration. See org.ghc.spring3.ControllerConfiguration for
// this example.
final AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext ();
dispatcherContext.setServletContext (servletContext);
dispatcherContext.register(ScProviderDirectory.class);
dispatcherContext.refresh ();
// Spin up the Spring DispatcherServlet (just like before) passing the just built
// application context. Load it like the regular Servlet that it is!
final ServletRegistration.Dynamic servlet = servletContext.addServlet ("spring", new DispatcherServlet(dispatcherContext));
servlet.setLoadOnStartup (1);
servlet.addMapping ("/"); // Make sure this is NOT "/*"!
}
}
Update 2 This is just weird. The Tomcat logs appear to identify two instances of my DeploymentDescriptor class. I verified that there is only one instance of this class in my .war file though. I have no idea where the second (phantom) instance is coming from, but at least this explains why the class is being scanned twice...
logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor#3b29642c]
logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor#432c4c7a]
The problem here was a Maven Overlay dumping crap a Spring xml configuration file into my application. For whatever reason this caused the WebApplicationInitializer.onStartup() to be called twice. Probably an initialization for the application context, and for the servlet context. Killed off the overlay, application is initializing as expected.
I had the same problem. The issue was that I had multiple spring-web*.jar like Biju K. suggested (one as part of the war, the other in shared/tomcat library).
I had the same problem. Running mvn clean in the web app module's directory and then starting up Tomcat solved it for me.

Spring does not abort bootstrapping on bean initialization Error when component scanning is enabled?

I have a web application with a spring configuration file. I have the following entry:
<bean id="flyway" class="xxx.FlywayTool" init-method="migrateOrFail"/>
The "flyway" bean is used to initialize and migrate the database.Now I have another bean defining the datasource the application should use:
<bean id="dataSource" class="..." depends-on="flyway">
this one depends on flyway to succeed.
Everything is working fine. Now, when the "flyway" bean throws an exception the bootstrapping of spring stops and the webapp startup is finished - all good.
Now i am starting to enable autowiring for certain components via:
<context:component-scan base-package="de.xxxxx.xxxxx" />
in some of the classes I depend on services which are also defined as beans in the xml configuration. and they I turn depend on the datasource mentioned above.
now the problem: as soon as I bootstrap the application now and "flyway" is throwing an exception the exception is swallowed by spring in the following section:
org.springframework.beans.factory.support.AbstractBeanFactory.getTypeForFactoryBean(String, RootBeanDefinition)
catch (BeanCreationException ex) {
// Can only happen when getting a FactoryBean.
if (logger.isDebugEnabled()) {
logger.debug("Ignoring bean creation exception on FactoryBean type check: " + ex);
}
onSuppressedException(ex);
return null;
}
and now spring tries, for every other dependend service (that depends on the datasource and therefore flyway) initialize all the beans which in turn results in the same procedure again and again.
This exceptional loop continues until spring is finished trying to instaniate every possible dependency instead of aborting after the first flyway error.
This strange behaviour only starts when I enable component scanning via
<context:component-scan ....
when this feature is disabled spring stops after the first flyway error happend. It also ends up in another class:
org.springframework.context.support.AbstractApplicationContext.refresh()
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
so this is the behaviour i would expect in the other case too.
our spring version: 3.0.6.RELEASE
this behaviour is also present with other classes throwing any runtime execption (not just flyway) is this a bug or expected behaviour?
any help highly appreciated
marcel
Put <context:component-scan... after your beans declaration in your XML file as nico_ekito said in comments.
Confirmed to work:
Marcel: wow, that seems to work. you reckon i should open a bug? or is this intended behaviour?

How to delay spring beans startup?

Having spring application (actually grails app) that runs apache-activemq server as spring bean and couple of apache-camel routes. Application use hibernate to work with database. The problem is simple. Activemq+Camel starts up BEFORE grails injects special methods into hibernate domain objects (actually save/update methods etc). So, if activemq already has some data on startup - camel starts processing messages w/o having grails DAO methods injected. This fails with grails.lang.MissingMethodException. Must delay activemq/camel startup before Grails injects special methods into domain objects.
If all these are defined as spring bean, you can use
<bean id="activeMqBean" depends-on="anotherBean" />
This will make sure anotherBean is initialized before activeMqBean
can you move MQ managment into a plugin? It would increase modularity and if you declare in plugin-descriptor
def loadAfter = ['hibernate']
you should have the desired behavior. Works for JBPM plugin
I am not sure in your case but lazy loading may also help e.g.
<bean id="lazybean" class="com.xxx.YourBean" lazy-init="true">
A lazily-initialized bean indicates to the IoC container to create bean instance when it is first requested. This can help you delay the loading of beans you want.
I know this question is pretty old, but I am now facing the same problem in the year 2015 - and this thread does not offer a solution for me.
I came up with a custom processor bean having a CountDownLatch, which I count down after bootstrapping the application. So the messages will be idled until the app has started fully and its working for me.
/**
* bootstrap latch processor
*/
#Log4j
class BootstrapLatchProcessor implements Processor {
private final CountDownLatch latch = new CountDownLatch(1)
#Override
void process(Exchange exchange) throws Exception {
if(latch.count > 0){
log.info "waiting for bootstrapped # ${exchange.fromEndpoint}"
latch.await()
}
exchange.out = exchange.in
}
/**
* mark the application as bootstrapped
*/
public void setBootstrapped(){
latch.countDown()
}
}
Then use it as a bean in your application and call the method setBootstrapped in your Bootstrap.groovy
Then in your RouteBuilder you put the processor between your endpoint and destination for all routes you expect messages coming in before the app has started:
from("activemq:a.in ").processRef('bootstrapProcessor').to("bean:handlerService?method=handle")

Resources