Customizing spring security requestmap in grails 2.3.5 - spring

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.

Related

Trying to call a class with constructor but #Autowired var is throwing Null Pointer Exception in Kotlin/Spring Boot

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.

spring boot component with string parameters

i have a component that reads a configuration value from application.properties and accepts a string parameter in its constructor as such..
#Component
public class Person
{
#Value("${greeting}")
String greeting;
String name;
public Person(String name)
{
this.name = name;
onGreet( greeting + ", " + name );
}
public void onGreet(String message)
{
}
}
I need to instantiate this component as follows and override its "onGreet" event in the calling code as follows:
Person jack = new Person("jack")
{
public void onGreet(String message)
{
System.out.println( message );
}
};
However I end up getting this..
Parameter 0 of constructor in demo11.Person required a bean of type 'java.lang.String' that could not be found.
My application.properties is as follows:
greeting=hello
What am I missing here? Thank you.
It is literally telling you that the only constructor that you have requires a parameter that Spring knows nothing about.
Add a #Value to that String name in the constructor (right before the parameter) like so public Person(#Value("${name}") String name) if you want Spring to initalize it or remove that constructor
EDIT: some more explanation:
Spring is a dependency injection container. Meaning you define beans and let Spring create and inject them for you. Defining beans can be done in several ways (Java configuration, annotations or xml) here you are using annotation way via #Component.
Now that you have defined your bean (aka component) for Spring it will create it. For it to create it it needs to call a constructor. For that you need to provide it with all information necessary for constructor call - meaning all parameters. If parameters are other classes they need to be defined as beans as well (For example via #Component) if they are simple types like String you need to provide #Value for them.
Lastly if you ever use new ... to define Spring managed beans then the whole Spring magic disappears since Spring doesnt know about this bean instantiation anymore and will not autowire anything into it. For all intenses and purposes Spring is not aware of any objects you create with new.

StateMachineRuntimePersister Instantiation getting failed because Spring not able to find its dependent bean MongoDbStateMachineRepository

I am new to spring state machines. I am trying to setup state machine for my transaction data and externalise it to mongo database. But i am getting error while creating "StateMachineRuntimePersister" bean.
Error says - Parameter 0 of method mongoPersist in com.pws.funder.config.PersistConfig required a bean of type 'org.springframework.statemachine.data.mongodb.MongoDbStateMachineRepository' that could not be found
#Configuration
public class PersistConfig {
#Bean(name="runtime")
public StateMachineRuntimePersister<WalletGatewayStates, WalletGatewayEvents, UUID> mongoPersist(
MongoDbStateMachineRepository mongoRepository) {
return new MongoDbPersistingStateMachineInterceptor<WalletGatewayStates,WalletGatewayEvents,UUID>(mongoRepository);
}
}
Any leads would be helpful.
Just create interface like this:
public interface StateMachineRepository extends MongoDbStateMachineRepository {
}
and pass it into mongoPersist method.
Spring automatically creates implementation from your repository interface and put this bean in the context.

proper way to use getBean() to create Beans dynamically

Setup :
- have a Several Configuration Class containing Bean definitions for my beans
- I will fetched a List of String from a database containing all the bean names and their corresponding Configuration class I want to instantiate dynamically
currently I will do a loop on the list and then call a method passing the beanName and the Configuration Class containing the bean definition:
private Object getBean(String beanName, Class configurationClass) {
Object bean = null;
AbstractApplicationContext context = new AnnotationConfigApplicationContext(
configurationClass);
bean = context.getBean(beanName);
return bean;
}
I would then use the returned object and used Reflections to invoke specific Methods based on a list I fetched from a database.
Question : Is there a proper way to do this ? because for every bean I want to create , I think performance will be affected.
You can use this in spring 4.1
I found the below example in this post - Spring MVC: How to return image in #ResponseBody?
public ResponseEntity<InputStreamResource> downloadUserAvatarImage(#PathVariable Long userId) {
GridFSDBFile gridFsFile = fileService.findUserAccountAvatarById(userId);
return ResponseEntity.ok()
.contentLength(gridFsFile.getLength())
.contentType(MediaType.parseMediaType(gridFsFile.getContentType()))
.body(new InputStreamResource(gridFsFile.getInputStream()));
}

Overzealous auto-wiring of spring bean properties in grails

I have a domain class:
class Searcher {
String names
List<String> getExperiments() {
return names.split(',');
}
void setExperiments(List<String> list) {
names = list.join(',');
}
}
and a bean defined in the resource file
experiments(com.fxpal.querium.experiment.ExperimentHolder) {
otherProp = 'foo'
}
The experiments bean is semantically different from the experiments property of the Searcher class.
How do I prevent Spring from auto-wiring a specific property of a specific bean? Since the experiments property of the Searcher bean is derived, I don't want Spring to touch it at all.
Why not just name your bean experimentHolder? By default its going to auto wire by name.

Resources