I'm upgrading spring form 4.3.3 to 5.2.7 and I'm having this exception:
Exception:
Related cause: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MyBean' defined in com.test: Unsatisfied dependency expressed through method 'MyBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
code :
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
#SuppressWarnings({ "unchecked" })
public MyBean MyBean(String url,
String user, String password, String id) {
return MyBean(url, user, password, id,
new HashMap<String, String>(),false);
}
PS 1: I'm using context.getBean with args to init my bean
PS 2: I'm facing this problem at the startup of the application even though im not using the bean at the startup ( I'm using #Scope("prototype") to init the bean whenever it's called)
PS 3: I didn't have the problem with spring 4.3.3
This could be due to an open issue with Spring 5.x.x version -
https://github.com/spring-projects/spring-framework/issues/21498
It talks about the issue which is specific to 5.x.x versions.
Since Spring 5.0 a #Bean can return null and the effect is to leave
the bean definition in the registry, but make the value not
autowirable. However, if there is another bean of the same type that
is not null, it does not become autowirable. Probably it should? The
exception from Spring doesn't mention the existence of either bean
(the null or the not null one)
Try marking the fields as Optional so it should not fail at startup.
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
#SuppressWarnings({ "unchecked" })
public Optional<MyBean> MyBean(Optional<String> url,
Optional<String> user, Optional<String> password, Optional<String> id) {
if(url.isEmpty() && user.isEmpty() && password.isEmpty() && id.isEmpty()) {
return Optional.empty();
}
return Optional.of(new MyBean(url, user, password, id,
new HashMap<String, String>(),false));
}
Update 1
I think this is more easier solution. Spring 5.0 added Nullable annotation and probably they added this annotation for this kind of scenario only.
API Documentation Link - https://docs.spring.io/spring/docs/5.0.0.RC1_to_5.0.0.RC2/Spring%20Framework%205.0.0.RC2/org/springframework/lang/Nullable.html
A common Spring annotation to declare that the annotated parameter or
return value could be null under some circumstances.
So all needed would be to mark the parameters and return type as Nullable.
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
#SuppressWarnings({ "unchecked" })
public #Nullable MyBean myBean(#Nullable String url,
#Nullable String user, #Nullable String password, #Nullable String id) {
if(url == null && user == null && password == null && id == null) {
return null;
}
return new MyBean(url, user, password, id,
new HashMap<String, String>(),false);
}
Related
The code below is defined in a shared module that is used by a couple of our apps, all using the same version of Spring.
#Component
public class CrowdRestAuthenticationManager implements SecurityManager {
private enum IAMObjectType {
USER,
GROUP
};
...
private List<String> getDirectParents(IAMObjectType objectType, String objectName, Predicate<String> filter)
throws IOException, InterruptedException {
objectName = URLEncoder.encode(objectName, "UTF-8");
String path;
switch (objectType) {
case USER:
path = String.format("/rest/usermanagement/1/user/group/direct?username=%s", objectName);
break;
case GROUP:
path = String.format("/rest/usermanagement/1/group/parent-group/direct?groupname=%s", objectName);
break;
default:
throw new RuntimeException("Unexpected objectType " + objectType);
}
...
}
private Collection<? extends GrantedAuthority> getWorkspaceBasedAuthorities(String username) {
// Get Workspace Roles
var workspaceMemberships = new HashMap<String, WorkspaceMembership>();
try {
List<String> workspacesRoles = getDirectParents(IAMObjectType.USER, username, getWorkspacePattern().asMatchPredicate());
...
}
}
}
I haven't defined any constructor for CrowdRestAuthenticationManager. All of the calls to getDirectParents are very much like the one demonstrated, calls from regular private instance methods within CrowdRestAuthenticationManager. The first argument is always a literal, one of the 2 enum values.
One of the apps (just one) won't start with the following error:
2022-06-23 10:57:33.541 WARN 75261 --- [ main]
ConfigServletWebServerApplicationContext : Exception encountered
during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'crowdRestAuthenticationManager.IAMObjectType' defined in URL
[jar:file:/Users/###/.m2/repository/###/core/0.0.1-SNAPSHOT/core-0.0.1-SNAPSHOT.jar!/###/security/CrowdRestAuthenticationManager$IAMObjectType.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'java.lang.String' available: expected at
least 1 bean which qualifies as autowire candidate. Dependency
annotations: {}
Description:
Parameter 0 of constructor in
###.security.CrowdRestAuthenticationManager$IAMObjectType
required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your
configuration.
This doesn't make sense to me. Why is it trying to construct an instance of this enum at startup? I haven't been able to identify the difference between the apps that is causing only one to have this problem.
Thanks!
I'm new to Kotlin and Spring Boot. I'm trying to call SearchService class with initialized constructors through ServiceClass, everything is fine until it's time to access Autowired env variable in SearchService - it throws Null Pointer Exception. I'm assuming I will have to Autowire SearchService in ServiceClass but then how will I initialize the constructor and name/isAlive variables in the performSearch method.
#Service
class ServiceClass {
#Autowired
lateinit var env: Environment
fun performSearch(req: String): String {
var searchService = SearchService("John", false)
result = searchService.searchAsync()
...
return result
}
}
#Repository
class SearchService(name: String = "", isAlive: Boolean = true) {
private var name: String = name
private var isAlive: Boolean = isAlive
#Autowired
lateinit var env: Environment
fun searchAsync(): String {
var endpoint = env.getProperty("endpoint").toString() + name //Error here
// makes call to get endpoint with Name and isAlive as params
...
return result
}
}
You're right that you need need to autowire the SearchService too. Spring can only autowire dependencies into components that it created. Because you're creating the SearchService yourself, Spring doesn't know that it exists, and won't autowire into it.
Your second question is: if you autowire the SearchService, how can you initialise its other properties like name and isAlive? This is a common problem with dependency injection, which arises when some of the parameters to a constructor are dependencies and others are data.
The solution is to use the factory design pattern. In dependency injection it's also sometimes called "assisted injection". Create another "factory" component whose only job is to create the SearchService for you:
#Component
class SearchServiceFactory(private val env: Environment) {
fun createSearchService(name: String = "", isAlive: Boolean = true) =
SearchService(env, name, isAlive)
}
You should then remove the #Repository annotation from the SearchService, since its creation isn't managed directly by Spring.
The factory can be autowired wherever you need to use it, and in turn has the Environment autowired into it. When you want to create the SearchService, you call createSearchService to provide values for the additional data parameters.
Your service class would change to the following:
#Service
class ServiceClass(private val factory: SearchServiceFactory) {
fun performSearch(req: String): String {
var searchService = factory.createSearchService("John", false)
result = searchService.searchAsync()
...
return result
}
}
Note that in the examples I've used constructor injection instead of #Autowired. Spring will automatically provide values for constructor arguments when instantiating a Kotlin class, the same as if it was an autowired field. Using constructor injection instead of field injection can help to ensure that problems like the one you encountered are detected at compile time rather than causing null pointer exceptions at runtime.
Two beans qualidied different with the same name are getting me an exception.
Exception message:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'tipusFonsSql', defined in class path resource [net/gencat/clt/arxius/connector/config/SqlGiacTxtResourceLoader.class], could not be registered. A bean with that name has already been defined in class path resource [net/gencat/clt/arxius/connector/config/SqlGiacImgResourceLoader.class] and overriding is disabled.
It's telling me that class SqlGiacTxtResourceLoader and class SqlGiacImgResourceLoader are defining two beans with a same name.
Nevertheless, they are "#Qualified" different. I mean:
Into SqlGiacImgResourceLoader
#Bean
#GiacImg #TipusFonsQ
public String tipusFonsSql() {
//...
}
Into SqlGiacTxtResourceLoader
#Bean
#GiacTxt #TipusFonsQ
public String tipusFonsSql() {
//...
}
As you can see, one is "#aulified" with #GiacImg annotation and the other ony by #GiacTxt.
Any ideas?
You have to name them like this
#Bean(name = "GiacImg TipusFonsQ")
public String tipusFonsSql() {
//...
}
and
#Bean(name = "GiacTxt TipusFonsQ")
public String tipusFonsSql() {
//...
}
to avoid bean conflict
There is 2 way to resolve this issue ( haha there could be many but I know below 2 approach):------
1st Method
change the bean name:---
#Bean(name = "custome bean name")
2nd Method
write down the below key in the application.properties:--
spring.main.allow-bean-definition-overriding=true
NOTE:-in your case you can change method name also
I am using Spring Cache abstraction based on annotations in my service.
I want to add a custom prefix to the key when added to the cache.
I created a constant and tried to add them to the methods as below.
private static final String CACHE_KEY_PREFIX="user";
#Cacheable(value = "users", key = "{ CACHE_KEY_PREFIX,#userId }")
#GetMapping("/{userId}")
public User getUser(#PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}
#CacheEvict(value = "users",key="{ CACHE_KEY_PREFIX,#userId }" )
#DeleteMapping
public void deleteUserByID(#PathVariable Long userId) {
LOG.info("deleting person with id {}", userId);
userRepository.delete(userId);
}
But, I get the stacktrace as below.
2018-06-12 13:35:48.911 ERROR 8728 --- [nio-8090-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'hash(#)'] with root cause
org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'hash(#)'
at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:129)
at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
Since I have multiple methods I do not want to hardcode the custom prefix in every method annotation.
Is there a way to add a custom prefix and avoid the exception I am seeing.
To use a constant in the annotation, you could include it as a fixed String like this:
#Cacheable(value = "users", key = "{'" + CACHE_KEY_PREFIX + "', #userId}")
#GetMapping("/{userId}")
public User getUser(#PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}
In this case, the compiler will resolve the value of attribute key to {'user', #userId}.
One of the ways is to create a custom RedisCacheConfiguration bean. Note that a semicolon just a common delimiter between the parts of a key, it has no special purpose.
A common prefix can be useful in a shared Redis instance to easily differentiate between the caches from different sources (example, from different microservices):
#Configuration
#EnableCaching
public class MyCacheConfig {
#Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.prefixCacheNameWith("myprefix:");
}
}
I am using Grails : 2.3.5
and Spring Security Core plugin : 1.2.7.3
In Grails Spring Security RequestMap is a separate table but in my application I want to use the requestMap concept with the existing table.
I have a RolePermissionMap table is there and I want to use this table for the RequestMap.
class Role{
Long id
String name
String description
}
class Permission{
Long id
String name
String description
String requestUrl
}
class RolePermissionMap {
Long id
Role role
Permission permission
}
Now I am overriding the loadRequestmaps() method by extending the RequestmapFilterInvocationDefinition class like below
class RolePermissionMapFilterInvocation extends RequestmapFilterInvocationDefinition {
#Override
protected Map<String, String> loadRequestmaps() {
Map<String, String> data = new HashMap<String, String>();
for (Object requestmap : ReflectionUtils.loadAllRequestmaps()) {
// Original code
//String urlPattern = ReflectionUtils.getRequestmapUrl(requestmap);
//String configAttribute = ReflectionUtils.getRequestmapConfigAttribute(requestmap);
//data.put(urlPattern, configAttribute);
// modified code
Permission permission = ReflectionUtils.getRequestmapUrl(requestmap);
Role role = ReflectionUtils.getRequestmapConfigAttribute(requestmap);
data.put(permission.getRequestUrl(), role.getName());
}
return data;
}
}
Then I will add this bean in resources.groovy
beans = {
objectDefinitionSource(RolePermissionMapFilterInvocation)
}
I am also trying to override the ReflectionUtils class also for getting the return types of getRequestmapUrl(requestmap) and getRequestmapConfigAttribute() methods also as required
When I run with this approach am getting exception below
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'objectDefinitionSource': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: url matcher is required
for resolving the url matcher I added a bean in resources.groovy but it failed
Do I need to create a bean with urlMaper or need to mention ReflectionUtils class any where ?
Please show me a way.. Thanks in Advance
The plugin expects the url field in your request map class to be a String, in order to use a different type you'd have to subclass RequestMapFilterInvocationDefinition to extract the URL patterns correctly, and install your custom class as the bean named objectDefinitionSource in your app's resources.groovy to replace the default bean definition supplied by SpringSecurityCoreGrailsPlugin.groovy in its doWithSpring.