Spring Security custom PermissionEvaluator configurations does not work properly - spring

I have a problem with my custom Spring Security PermissionEvaluator. So,
the CustomPermissionEvaluator needs that service to do its work.
#Service
public class MyService {
// methods....
}
And here's the evaluator itself.
public class CustomPermissionEvaluator implements PermissionEvaluator {
private MyService service;
public CustromPermissionEvaluator( MyService service ) {
this.service = service;
}
// hasPermission methods...
}
And here's configurations
#Configuration
#EnableGlobalMethodSecurity( prePostEnabled = true )
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Autowired
private MyService service;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
CustomPermissionEvaluator permissionEvaluator = new CustomPermissionEvaluator( service );
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator( permissionEvaluator );
return expressionHandler;
}
}
So when #PreAuthorize( "hasPermission( ... )" ) should be invoked, nothing happens. But when I put that dependency straight to the CustomPermissionEvaluator's constructor, without ApplicationContext and autowiring, everything works perfect. I have printed service object to the log file and it is not null. So, what is wrong?

I had this same problem and had to use the #Lazy annotation:
#Lazy #Autowired
private MyService service;
It appears the security stuff is bootstrapped before the rest of the Spring config. I guess #Lazy allows a reference to be injected but not actually resolved until used.

After spending hours , this is the only solution solution worked for me. thanks #hvgotcodes.
so what i did is
annotate the CustomPermissionEvaluator with #component.
and annotate MyService with #Lazy #Autowired
#Component
Class CustomPermissionEvaluator {
#Lazy #Autowired
private MyService service;
}
If I user the #Lazy #Autowired in configuration MethodSecurityConfiguration then it does not worked

Related

#ConfigurationProperties, #Value not Working YET Passing the Tests

I have a strange problem reading configuration, none of solutions I've seen seem to work. Here is my code:
#SpringBootApplication
#EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Here is my properties class
#Component
#ConfigurationProperties(prefix = "my")
#Data
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class MyProperties {
private String host;
private int port;
}
I then use MyProperties class in my class using #Autowired:
#Autowired
private MyProperties props;
However, I'm getting null for my props object.
Strangely, this is passing the tests just perfectly:
#SpringBootTest
class ApplicationTests {
#Autowired
private MyProperties props;
#Test
void test_configuration() {
Assertions.assertEquals(props.getHost(), "xx.xx.xx.xx");//pass!
Assertions.assertEquals(props.getPort(), xxxxxx);//pass!
}
}
It has totally refused to work, and so has #Value injection. What could I be missing?
EDIT
Here's complete code of how I'm using #Autowired on MyProperties (I've included #Value which is also not working)
#Slf4j
#Component //also tried #Configurable, #Service
public class MyService {
#Autowired
private MyProperties props;
#Value("localhost")
public String host;
public void post() {
log.info(host + props);// =null and null
}
}
EDIT2
However, I've noticed that on the controller, it works perfectly okay:
#Slf4j
#RestController
#Service
public class Main {
#Autowired
private MyProperties props;
#Value("localhost")
private String host;
#GetMapping("/post")
public void post() {
log.info(host + props);//=it's perfect!
new MyService().post();// calling MyService - where #Autowired or #Value is failing
}
}
The reason this isn't working is because the MyService you're using isn't a Spring bean, but an instance you created by yourself (using new MyService()).
To make this work, you should autowire MyService, in stead of creating your own instance:
#Slf4j
#RestController
public class Main {
#Autowired // Autowire MyService
private MyService myService;
#GetMapping("/post")
public void post() {
myService.post(); // Use the myService field
}
}
For more information, look at this Q&A: Why is my Spring #Autowired field null.
UPDATE:
new MyService() is not a "spring bean", thus can't be auto-wired with anything!;)
1. Lombok
Some people use Project Lombok to add getters and setters automatically. Make sure that Lombok does not generate any particular constructor for such a type, as it is used automatically by the container to instantiate the object.
With "such a type" ConfigurationProperties is referred in Externalized Configuration (one of my favorite chapters;) More Exact: 2.8.1. JavaBean properties binding, at the bottom of second "Note!" ;)
So this could be a reason (for strange behavior).

Spring Boot and/or Vaadin autowiring behaviors I do not understand

I am working on a Spring Boot application an am having issues where items are not being auto-wired as I expect. What is adding to this confusion is that I have another Spring Boot application that also happens to involve Vaadin. In this application, auto-wiring seems more "automated".
Here is what I mean. In the Vaadin app, a #Service object, is injected into a Vaadin "view" with little effort. Additionally, the service object itself is injected with a Repository object. I need to do almost nothing to make this all happen.
In my other non-Vaadin application, I set up the code to do similar things, but in this case, it does not work. The application fails to start and complains as below:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.mycompany.app.backend.service.TaskMasterService required a bean of type 'com.mycompany.app.backend.repository.TaskMasterRepository' that could not be found.
Action:
Consider defining a bean of type 'com.mycompany.app.backend.repository.TaskMasterRepository' in your configuration.
I assume that I'm missing some configuration somewhere, or that the Vaadin application has "extra" functionality added that makes this work.
Here are snippets of the Vaadin application:
TasksView.java:
#Route("main")
public class TasksView extends VerticalLayout {
private final TaskService taskService;
private final TaskNoteService noteService;
public TasksView(TaskService taskService, TaskNoteService noteService) {
this.taskService = taskService;
this.noteService = noteService;
}
...
}
TaskService.java:
#Service
#Transactional
public class TaskService {
private TaskRepository taskRepo;
public TaskService(TaskRepository taskRepo) {
this.taskRepo = taskRepo;
}
...
}
TaskRepository.java:
public interface TaskRepository extends JpaRepository<Task, Long>, TaskRepositoryCustom {
...
}
I don't need to #Autowired anything or provide a #Configuration class or define a #Bean anywhere. It just works.
Here are some snippets from the non-Vaadin application:
IngesterRunner.java:
#Service
public class IngesterRunner {
private TaskMasterService tmService;
private TaskRelationshipService trService;
private VariantDetailService vdService;
public IngesterRunner(TaskMasterService tmService, TaskRelationshipService trService,
VariantDetailService vdService) {
this.tmService = tmService;
this.trService = trService;
this.vdService = vdService;
}
...
}
TaskMasterService.java:
#Service
#Transactional
public class TaskMasterService {
private final TaskMasterRepository repo;
public TaskMasterService(TaskMasterRepository repo) {
this.repo = repo;
}
...
}
TaskMasterRepository.java:
package com.mycompany.app.backend.repository;
public interface TaskMasterRepository extends JpaRepository<TaskMaster, Long> {
}
JPAConfiguration.java:
#Configuration
#EnableJpaRepositories(basePackages = "com.mycompany.app.backend.repository", transactionManagerRef = "jpaTransactionManager")
#EnableTransactionManagement
public class JPAConfiguration {
private static final String[] ENTITY_PACKAGES_TO_SCAN = {
"com.mycompany.app.backend.entity" };
...
}
I don't understand what is different about the first application that makes auto-wiring work so much more smoothly. Is it something I have in my pom.xml? Is it some sort of extra support provided by Vaadin?
If requested, I can try to include the POM files if that will help.
Update:
I have tried a number of suggestions, but none seem to have any effect. I added #Autowired annotations, but it makes no difference.
#Service
public class IngesterRunner {
private TaskMasterService tmService;
private TaskRelationshipService trService;
private VariantDetailService vdService;
public IngesterRunner(#Autowired TaskMasterService tmService,
#Autowired TaskRelationshipService trService, #Autowired VariantDetailService vdService) {
this.tmService = tmService;
this.trService = trService;
this.vdService = vdService;
}
...
}
#Service
#Transactional
public class TaskMasterService {
private final TaskMasterRepository repo;
public TaskMasterService(#Autowired TaskMasterRepository repo) {
this.repo = repo;
}
...
}
#Repository annotation in TaskMasterRepository.java, like
#Repository
public interface TaskMasterRepository extends JpaRepository<TaskMaster, Long> {
}

Does spring bean self injection works in new spring versions?

#Service
public class UserService implements Service{
#Autowired
private Service self;
}
Does the code above works fine in Spring new versions (5.*)?
( I could check by myself but I wanna know 100%, but myself I may screw it up somehow )
Also I know workarounds:
#Service(value = "someService")
public class UserService implements Service{
#Resource(name = "someService")
private Service self;
}
OR
#Autowired
private ApplicationContext applicationContext;
So I'm not just asking for nothing, I need to know 100%
I need an advice from professionals, I don't believe to myself experiments, because I'm not so much experienced in Spring ( e.g. there are much nebulous configs there for me) . Hope this clarifies why I'm asking rather than experiment.
Ok I found the answer:
With Spring 4 it's possible to Self autowired
#Service
#Transactional
public class UserServiceImpl implements UserService{
#Autowired
private UserRepository repository;
#Autowired
private UserService userService;
#Override
public void update(int id){
repository.findOne(id).setName("ddd");
}
#Override
public void save(Users user) {
repository.save(user);
userService.update(1);
}
}

#Autowired not working in spring boot

I am working on spring-boot application. In that application #Autowired is not working for some classes.
I have below classes in spring boot application:
#Component
public class SessionUser {
private static final String SESSION_PRINCIPAL = "session.principal";
#Autowired
private HttpSession httpSession;
//more code
}
#RestController
public class RefreshUserPermissionsRequestHandler {
#Autowired
TaskTrigger taskTrigger;
#Autowired
private SessionUser sessionUser;
}
public class LocalFileUserProviderImpl {
#Autowired
private SessionUser sessionUser;
//more code
}
In RefreshUserPermissionsRequestHandler, the SessionUser bean is injecting properly, but in LocalFileUserProviderImpl it's not working. Even I tried to annotate LocalFileUserProviderImpl with #RestController and #Controller but both are not working.
Can anyone help me what is going wrong here? Please let me know if any further info is required.

Why spring #autowired is null?

I'm trying to autowire a service in my rest controller like these:
rest controller:
#ApplicationPath("/greetings")
#Component(immediate = true, service = Application.class)
public class RestControllerApplication extends Application {
#Autowired
private MyService myService;
public Set<Object> getSingletons() {
return Collections.<Object>singleton(this);
}
#POST
#Path("/getUploadType")
#Produces("application/json")
public JsonObject getUploadType() {
...
myService.findUploadTypes();
...
}
}
service:
#Component
public class UploadService {
private static final Logger log = Logger.getLogger(UploadService.class);
#Autowired
private OneDAO oneDAO;
#Autowired
private TwoDAO twoDAO;
...
}
but in my rest controller, uploade service is null. Why?
Spring uses its own set of annotations. Instead of #Path plus #[HTTP method] you should use #RequestMapping.
You can find an example here
There is also an extended example here
I have got access to my bean, with these few line of code:
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyService myService = context.getBean(MyService.class);
You are declaring a UploadService as #Component but trying to autowire a MyService instance in your controller...
There are two options: you can declare correct service type in your controller or you can make UploadService inheriting from MyService.

Resources