I'm working on an update version of grail-oauth-plugin that support last spring-oauth
My plugin version works good and I have implemented a workin oauth2 server.
But now I want to add a custom-grant defined like this
def doWithSpring = {
myTokenGranter(MyTokenGranter)
xmlns oauth:"http://www.springframework.org/schema/security/oauth2"
oauth.'authorization-server'( /* ... many definitions here ... */){
/* ... many definitions here ... */
oauth.'custom-grant'('token-granter-ref': "myTokenGranter")
}
}
But I get an exception telling me:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myTokenGranter'
But the bean myTokenGranter is defined as you can see. And If I remove the custom-grant definition the project starts and I can access the myTokenGranter bean.
Looking to a fullstack trace I see that the exception occur in the spring oatuh2 server bean definition parse AuthorizationServerBeanDefinitionParser.java in the line where it try to find my bean
parserContext.getRegistry().getBeanDefinition(customGranterRef);
where customGranterRef = "myTokenGranter"
so I suspect there is a bug in Spring Ouath or in Grails BeanBuilder that does not let my "myTokenGranter" to be visible in the server parser. Or making some error in grails bean definition DSL.
Thank you for your interest.
Debugging the app more deeply I have found that the problem probably is in how grails BeanBuilder work in translating namespaced spring DSL.
If I debug the point where my bean is checked (in AuthorizationServerBeanDefinitionParser.java)
at row
parserContext.getRegistry().getBeanDefinition(customGranterRef);
if I check che result of
parserContext.getRegistry().getBeanDefinitionNames()
it show me only this beans
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor
org.springframework.aop.config.internalAutoProxyCreator
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0
org.springframework.transaction.interceptor.TransactionInterceptor#0
org.springframework.transaction.config.internalTransactionAdvisor
oauth2TokenGranter
oauth2AuthorizationCodeServices
oauth2AuthorizationRequestManager]
And not all other decleared beans...
The problem exist even if I move the ouath server declaration inside resources.xml, keeping my custom token granter bean declaration inside resources.groovy.
But the problem solves if I move the custom token bean declaration inside resources.xml.
I don't really know how the BeanBuilder DSL works, but it seems like the problem is there if there is a problem (your example works just fine in XML). Can you do it in two steps, so the bean definition for myTokenGranter is definitely available when the OAuth2 namepsace is handled?
Solved hacking Spring Security Oauth
see this commit
Related
Im trying to follow the guide for Hybris123 version 19.05, but when creating new services I get a problem where the spring framework does not recognize my service.
I tried to change the neme of the variable but honestly Im not sure what to do.
The errorIm getting is "org.springframework.beans.FatalBeanException: Context hybris Global Context Factory couldn't be created correctly due to, Error creating bean with name 'applicationEventMulticaster': Unsatisfied dependency expressed through method 'setAllDecorators' parameter 0; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [concerttours.service.impl.DefaultBandService] for bean with name 'defaultBandService' defined in class path resource [concerttours-spring.xml]; nested exception is java.lang.ClassNotFoundException"
The code Im using in spring is:
<alias name = "defaultBandService" alias = "DefaultBandService"/>
<bean id = "defaultBandService" class = "concerttours.service.impl.DefaultBandService" >
<property name = "bandDAO" ref = "bandDAO" />
</bean>
And when I use the IDE for looking a file with the name DefaultBandService it recognizethe service that Im trying to use but the spring framework does not. In the service tried to use a spring Tag like component but it didnt work.
I expect spring to recgonize the bean and let me run the hybris server
Use your IDE to look for the class(i.e DefaultBandService).
Check the package of the class(most probably the first line of the file).
Make sure that the package is specified correctly in your spring xml File.
Make sure that the class is in the same extension as the Spring file. If it is not, then a dependency needs to be added in extensioninfo.xml.
Run "ant clean all" and start the Server again.
The project I am working at the moment uses camel as the routing framework.
When configuring camel context in spring we pass a property file that contains a bunch of global properties needed when configuring camel routes or for controlling run time behavior:
<camel:camelContext xmlns="http://camel.apache.org/schema/spring" id="my-id">
<camel:propertyPlaceholder location="my-system.properties" id="global-properties"/>
...
</camel:camelContext>
and say my-system.properties has an entry like below:
my-system.properties
# Global properties that control my-system configuration and run time
...
foo={{bar}}
...
When configuring the routes I can access foo property using the {{foo}} notation. It is also available to other beans using #PropertyInject annotation. However there is one use case in my design when a plain POJO not created by spring (an enum instead but this is not relevant) needs to access my foo property. Because this POJO it is passed the CamelContext as a method argument I find it natural to think I should be able to get the value of foo from there. However I spent a bit of time and could not figure out by myself how.
I know I can load the properties file again or even get the system property System.getProperty("bar") and everything will work but it looks like cheating to me.
There is an api on CamelContext to resolve property placeholders - its the resolvePropertyPlaceholders method:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/CamelContext.html#resolvePropertyPlaceholders(java.lang.String)
If your POJO is not being managed by the SpringContext I don't see any way you can automatically inject the property. Although your approach may not seem the most fancy or elegant, it has the advantage of not giving you any overhead you could have by using another injection tool.
I am sorry that this is probably too vague and generel of a question. I am trying to bring up a huge legacy project with tons of spring wirings, and I am getting this error:
The bizzare thing is this error does not tell me on which xml, which bean id, the error occurs.
I certainly don't expect anybody to point me to where to fix.. My question is, how do spring experts even debug this kind of uninformative error message?
Yes, I understand it must be one of my xml bean was set wrongly. But shouldn't the error message make it easier for me to find out which bean?
Any advice would be extremely appreciated.
00:09:00.640 [main] ERROR com.xxxx.yyyy.zzzzzz.AppMain - Failed to initialize BLAH BLAH BLAH
java.lang.IllegalStateException: No bean class specified on bean definition
at org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(AbstractBeanDefinition.java:381) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:154) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1035) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:939) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
It's thrown by following piece of code. The init() methods takes in the spring xml files and do its wiring.
try {
AppMain.init(args_);
} catch (Exception e) {
_LOGGER.error("Failed to initialize BLAH BLAH BLAH", e);
System.exit(-1);
}
That's a piece of the sources where it fails
You can try to set a breakpoint there in the Exception throwing. Or add the spring code rather than jar file and try to debug there.
public Class<?> getBeanClass() throws IllegalStateException {
Object beanClassObject = this.beanClass;
if (beanClassObject == null) {
throw new IllegalStateException("No bean class specified on bean definition");
}
if (!(beanClassObject instanceof Class)) {
throw new IllegalStateException(
"Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
}
return (Class) beanClassObject;
}
My question is, how do spring experts even debug this kind of
uninformative error message?
I'd argue that the error message is very informative. It states that something has tried to put your application in an illegal state. In this particular example, your context was configured in a way where some bean's class is not specified. This is typically caused by forgetting to put a class attribute in a <bean> declaration.
Spring creates BeanDefinition objects for each bean in your context. These can be from your <bean> declarations or other XML elements or Java configuration elements (from #Configuration, #Component, etc.). Almost everything involved in a Spring ApplicationContext is a bean.
You can be pretty sure that Spring's infrastructure beans aren't to blame for this. Spring is an established framework with tons of work put into it and testing done before every release. The immediately obvious alternative is that somewhere in your code you forgot to specify a class. Did you, for example, try to make an abstract <bean> but forget to add the abstract="true"? Did you register a BeanDefinitionParser and create BeanDefinitions without a class? Did you create BeanDefinitionPostProcessor and remove BeanDefinition class values?
Those are the things I would start with.
I have a spring application (A) which uses a transient dependency (B) which in itself is based on Spring as well.
So to summarize, war A & jar B are both spring projects. B is a dependency of A.
One of the attributes of a class in B is decorated in the following way
#Resource(name="thisIsTheTargetRef")
private String hardToFindMe;
I went through the application context files of A & B but I do not find a declaration of a bean with the id 'thisIsTheTargetRef'. But somehow the logs show that the .hardToFindMe. attr gets wired with 'thisIsTheTargetRef' bean. I search through both the A & B projects including all other dependencies to see if this is getting picked up from somewhere else. No dice. I even inspected the Component-scan packages but with no luck. I also did a hard text search for 'thisIsTheTargetRef' in both A & B including the dependency projects. I still don't find it.
Here is a log snippet showing that the bean is still getting wired.
[#|2014-01-27T18:23:16.654+0000|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=10;_ThreadName=Thread-3;|77875 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory {} null - Returning cached instance of singleton bean 'thisIsTheTargetRef'
|#]
[#|2014-01-27T18:23:46.640+0000|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=10;_ThreadName=Thread-3;|18:23:46,639 INFO [XmlWebApplicationContext:1332] Bean 'thisIsTheTargetRef' of type [class org.springframework.jndi.JndiObjectFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|#]
It does appears that I'm missing something here. There might have been a dependency that I have missed looking into and my eyes are just fooling me. But any other obvious places that I should look at?
If not, based on the logs, XmlWebApplicationContext:1332 is referred as the location for the bean. How can I debug to find out where it is getting picked from? Thanks.
You might be lucky by defining a watch/breakpoint on the field you know where it is injected. During the debugging you should get a stop during the autowiring process and you will see which class is wired. This should help identifing it and then check occurences for this class.
I'm not sure if you can directly find out from where this bean is loaded. One hint should be either the annotationprocessor or xmlprocessor.
To be exact, how can I get the value of the <display-name> tag under the <web-app> tag stored in an application's web.xml in a Spring application context configuration XML file.
Ideally I would like something like the following...
<bean><property value="${servletContext.servletContextName}/></bean>
It seem like ServletContext.getServletContextName() does what I want but I can't seem to figure out how to get a handle on that in the Spring application context file.
Ok, the answer is trivial in Spring 3.0.x. Per the documentation for ServletContextFactory
Deprecated. as of Spring 3.0, since "servletContext" is now available as a default bean in every WebApplicationContext
So I decided to try the following and it worked!
<bean><property value="#{servletContext.servletContextName}/></bean>
Since servletContext object is implicitly defined we can access it via Spring EL using the #{} syntax.
I don't think you can do this via the XML config.
You can autowire a bean to receive the ServletContext object (or implement ServletContextAware), and fetch it from that programmatically, but I don't think the XML expressions have any visibility of it.
Maybe try the Expression Language?
<bean>
<property value="#{T(javax.servlet.ServletContext).getServletContextName()}"/>
</bean>
I suspect that would print null if it works though, since there is no context yet.