ApplicationListener is getting fired twice - spring

This is firing twice does anyone know why:
#Component
public class AuthenticationFailureListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
#Autowired
private LoginAttemptService loginAttemptService;
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) {
String email = (String) e.getAuthentication().getPrincipal();
loginAttemptService.loginFailed(email);
}
}

Related

EventListener don't catch events

I have problem with listening to AuthenticationSuccessEvent and AuthenticationFailureBadCredentialsEvent, none of this event is triggered. Here's my code:
#Component
#RequiredArgsConstructor
public class AuthenticationFailureListener {
private final LoginAttemptService loginAttemptService;
#EventListener
public void onAuthenticationFailure(AuthenticationFailureBadCredentialsEvent event) {
Object principal = event.getAuthentication().getPrincipal();
if (principal instanceof String) {
String username = (String) principal;
loginAttemptService.addUserLoginAttemptCache(username);
}
System.out.println("onAuthenticationFailure");
}
}
Second class
#Component
#RequiredArgsConstructor
public class AuthenticationSuccessListener {
private final LoginAttemptService loginAttemptService;
#EventListener
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
Object principal = event.getAuthentication().getPrincipal();
if (principal instanceof UserPrincipal) {
UserPrincipal user = (UserPrincipal) principal;
loginAttemptService.evictUserFromLoginAttemptCache(user.getUsername());
}
System.out.println("onAuthenticationSuccess");
}
}
and I added this to Security Configuration
#Bean
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
But my fail and successful login don't trigger any listener :disappointed: I'm using spring security 5.7.6. I've checked and all these beans are created. What's maybe a reason for that behavior ?

Is it safe to call something in my RestController from my WebSocketHandler?

I guess this is a bit of a threadsafe question, as I'm not sure how Spring Boot handles beans and web service calls and incoming websocket data.
Is it safe to call controller.doSomething() from McpWebSocketHandler, if I know MCPController.ping() also calls it?
Also, if I have the GameUnitService Autowired in both MCPController and McpWebSocketHandler, will there be any thread contention?
#SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
#RestController
public class MCPController implements MqttListener {
Logger log = LoggerFactory.getLogger(MCPController.class);
#Autowired private JdbcTemplate jdbc;
#Autowired private GameUnitService gameUnitService;
#GetMapping("/ping")
public Object ping(HttpServletRequest request) {
String remoteAddr = request.getHeader(FORWARDED) == null ? request.getRemoteAddr() : request.getRemoteAddr() + "/" + request.getHeader(FORWARDED);
log.info("Got ping from {}", remoteAddr);
doSomething();
return new Response(true, ErrorCode.OK, "pong");
}
public String doSomething() {
return gameUnitService.doSomethingWithDatabase();
}
}
public class McpWebSocketHandler extends AbstractWebSocketHandler {
private ApplicationContext appContext;
private GameUnitService gameUnitService;
private MCPController controller;
public McpWebSocketHandler(ApplicationContext appContext,GameUnitService gameUnitService) {
this.appContext = appContext;
this.gameUnitService = gameUnitService;
controller = (MCPController)appContext.getBean("MCPController");
}
#Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
String response = controller.doSomething(); //is this safe?
session.sendMessage(new TextMessage(response));
}
}
#Configuration
#EnableWebSocket
#ComponentScan(basePackageClasses = McpApplication.class)
//public class McpWebSocketConfig implements WebSocketConfigurer, MqttListener {
public class McpWebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(McpWebSocketConfig.class);
#Autowired private ApplicationContext appContext;
#Autowired private GameUnitService gameUnitService;
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new McpWebSocketHandler(appContext,gameUnitService), "/socket").setAllowedOrigins("*");
registry.addHandler(new McpWebSocketHandler(appContext,gameUnitService), "/").setAllowedOrigins("*");
}
...
}

Spring Boot Isolation.SERIALIZABLE not working

I need help with this scenario, in theory the isolation level of Serializable should stop delete from happening, but in this scenario it still deletes the row with id 1, I have tried #EnableTransactionManagement and isolation repeatable read, it still doesn't block the delete nor cause the delete to throw exception
In summary, I need to stop any delete invocation whenever the update method is still ongoing
I am using H2 in memory database for this sample
Thanks
Entity:
public class Something {
#Id
private Integer id;
private String name;
private String desc;
}
Repo:
public interface SomeRepository extends JpaRepository<Something, Integer> {
}
Service:
#Service
public class SomeService {
#Autowired
private SomeRepository someRepository;
public void deleteSomething2(Something something) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
someRepository.delete(something);
}
#Transactional(isolation = Isolation.SERIALIZABLE)
public void updateSomething2(Something something) {
Something something1 = someRepository.findById(1).get();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
something1.setName("namanama");
someRepository.saveAndFlush(something1);
}
Test:
#RunWith(SpringRunner.class)
#SpringBootTest
public class DemoApplicationTests {
#Autowired
private SomeService service;
#Test
public void test() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future> futures = new ArrayList<>();
futures.add(executorService.submit(() -> service.updateSomething2(Something.builder().id(1).name("namaone").build())));
futures.add(executorService.submit(() -> service.deleteSomething2(Something.builder().id(1).build())));
while(futures.stream().filter(f -> f.isDone() == false).count() > 0) {
Thread.sleep(3000);
}
List<Something> all = service.findAll();
System.out.println(all);
}
}

MongoTemplate null pointer exception in class

I have been looking at other answers but none of the seem to work for me, I have a spring boot application where I am using mongo and kafka. In the main class where my run() method is I am able to #Autowired mongoTemplate and it works but then in another class I did the same and I am getting a null pointer exception on the mongoTemplate.
Here are both classes:
Working
#SpringBootApplication
public class ProducerConsumerApplication implements CommandLineRunner {
public static Logger logger = LoggerFactory.getLogger(ProducerConsumerApplication.class);
public static void main(String[] args) {
SpringApplication.run(ProducerConsumerApplication.class, args).close();
}
#Autowired
private Sender sender;
#Autowired
MongoTemplate mongoTemplate;
#Override
public void run(String... strings) throws Exception {
Message msg = new Message();
msg.setCurrentNode("my_node");
msg.setStartTime(System.currentTimeMillis());
String json = "{ \"color\" : \"Orange\", \"type\" : \"BMW\" }";
ObjectMapper objectMapper = new ObjectMapper();
msg.setTest(objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){}));
sender.send(msg);
mongoTemplate.createCollection("test123");
mongoTemplate.dropCollection("test123");
}
Not working
#Component
public class ParentNode extends Node{
#Autowired
public MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}
}
Thank you for the help. It is much appreciated.
can you try to inject dependency with setter or constructor:
Method 1:
#Component
public class ParentNode extends Node{
#Autowired
public ParentNode(MongoTemplate mongoTemplate){
this.mongoTemplate = mongoTemplate;
}
private final MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}
Method 2:
#Component
public class ParentNode extends Node{
#Autowired
public void setMongoTemplate(MongoTemplate mongoTemplate){
ParentNode.mongoTemplate = mongoTemplate;
}
static private MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}

Issue in calling validator automic with #Valid in Spring controller

I am trying to call validator from controller using #Valid annotation, but control is not going to validator and proceeding without validating.
Controller
#Controller
#RequestMapping(value="/event")
public class EventController {
#Autowired
private EventService eventService;
#Autowired
EventValidator eventValidator;
#InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(eventValidator);
}
#RequestMapping(value="/add_event",method = RequestMethod.POST,produces=MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<AjaxJSONResponse> postAddEventForm(#Valid #RequestPart("event") Event event, MultipartHttpServletRequest request) {
Boolean inserted = eventService.addEvent(event);
String contextPath = request.getContextPath();
String redirectURL = StringUtils.isEmpty(contextPath)?"/event":contextPath+"/event";
return new ResponseEntity<AjaxJSONResponse>(new AjaxJSONResponse(inserted,"Event Added Successfully",redirectURL), HttpStatus.OK);
}
}
Validator
#Component
public class EventValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return Event.class.isAssignableFrom(clazz);
}
#Override
public void validate(Object target, Errors errors) {
Event event = (Event)target;
if (event.getEventName() == null ||!StringUtils.hasText(event.getEventName())) {
errors.rejectValue("eventName", "", "Event Name is empty");
}
}
}
Please help on this.
Thank in advance

Resources