Spring advice does not work as expected - spring

I am new in Spring AOP, and I have create an application to learn the Spring AOP, however I found that the Aspect does not work as expected, this is the core code:
Target:
public interface UserService {
void getUserList();
}
#Component
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
#Override
public void getUserList() {
this.userDao.getUserList();
}
}
Aspect:
#Aspect
public class LoggingAspect {
#Pointcut("execution(* com.kk.service.impl.UserServiceImpl(..))")
public void logTargetUserService() {
}
#Before("execution(* com.kk.service.impl.UserServiceImpl.getUserList(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
spring.xml:
<context:component-scan base-package="com.kk"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
Application:
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
UserServiceImpl userService = context.getBean(UserServiceImpl.class);
userService.getUserList();
}
}
When I run it I only got this output:
get user list at dao
It seems that the advise does not run at all.
What is going on?

You should regist your bean as like this
<bean id="loggingAspect" class="your.package.LoggingAspect"/>

Related

How to use Spring boot AutoWired and ScheduledExecutorService?

I need to use autowired in more than one class with ScheduledExecutorService, what I have tried is shown in this code. logging size of User list in below example always shows 0, even after user added to arraylist. How to properly use Autowired and ScheduledExecutorService in spring boot?
#Component
public class AnotherClass {
List<User> users = new ArrayList();
public void addUser(User user){
users.add(user);
}
public void logUsers(){
logger.info("User size " + users.size()); <================= Always logs 0, when called from executor
}
}
#RestController
public class SecondClass {
#Autowired
private AnotherClass anotherClass;
#GetMapping(value="/user/test")
public void logUsers(){
anotherClass.addUser(new User());
}
}
Application Class
#Component
#SpringBootApplication
public class SpringBootDemoApplication {
private ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
#Autowired
private AnotherClass anotherClass;
#PostConstruct
public void init() {
logger();
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
public void logger(){
exec.scheduleAtFixedRate(new Runnable(){
#Override
public void run(){
try {
anotherClass.logUsers();
}catch (Exception e){
}
}
}, 2000, 1000, TimeUnit.MILLISECONDS);
}
}
The code works if you use the Spring #Autowired and not the #AutoWired Annotation.

Why Spring Boot AOP pointcut not triggered

wanner test spring boot(1.5.20) aop with minimum code
class being aopped,
#Component
public class Test {
public Test() {
System.out.println("test constr");
}
public void print() {
System.out.println("test print");
}
}
aop class
#Aspect
#Component
public class LoggingAspect {
public LoggingAspect() {
System.out.println("aspect constr");
}
#After("execution(* *.Test.*(..))")
public void log(JoinPoint joinPoint) {
System.out.println("aspect print");
}
}
main class
#SpringBootApplication
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(AopApplication.class, args);
}
#Autowired
private Test test;
#Override
public void run(String... strings) throws Exception {
test.print();
}
}
both Test bean and LoggingAspect bean is created. Test.pring is executed. However, the pointcut log() is never triggered. I searched so and found no answer. I also tried #EnableAspectJAutoProxy with proxyTargetClass = True or False. In my understanding this params force to use cglib for Test class.
please let me know what I missed
figure out. change from .Test. to com.example.aop.Test.*, then works.

Spring Boot + DynamoDBTypeConverter dependancy injection

I'm trying to get DI working with a sample DynamoDBTypeConverter I'm playing around with and having no luck at all :( My service is always null and throws an error as a result in my jUnit test.
Here's my converter:
#Component
public class ArmTypeConverter implements DynamoDBTypeConverter<String, Arm> {
#Autowired
private ArmRepository armRepository;
#Override
public String convert(Arm Arm) {
return arm.getId();
}
#Override
public Arm unconvert(String id) {
return armRepository.findOne(id);
}
}
My application main:
#SpringBootApplication
#ComponentScan
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving=EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableAutoConfiguration
public class ArmApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(ArmApplication.class, args);
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
My service:
#Service
public class ArmServiceImpl implements ArmService {
#Autowired
private ArmRepository armRepository;
#Override
public Arm create(String length, Set<Register> registers) {
Date now = new Date();
Arm arm = new Arm();
arm.setLength("85cm");
return armRepository.save(arm);
}
}
My Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class ArmServiceTests {
#Autowired
private ArmService armService;
#Autowired
private TorsoService torsoService;
private Arm arm;
#Before
public void before() {
arm = armService.create("85cm", null);
torsoService.create("150cm", arm);
}
#After
public void after() {
// do nothing for now...
}
#Test
#WithUserDetails("admin#somewhere.com")
public void getArmTest() {
Arm c = armService.getArm(arm.getId());
assertThat(c).isNotNull();
assertThat(c.getId()).isEqualTo(arm.getId());
}
}
What am I doing wrong?
The issue was that I didn't have load time weaving configured properly

How to use annotation and avoid xml configuration in spring framework

I have designed a packing structure.
Controller
Delegates (which is helper class) - this class do all the business and return the value to Controllers.
Service
Service Implementation
DAO
DAO Implementation.
I want to implement autowired (Annotation) concept and would like to avoid xml configuration such as service and DAO configuration on spring-bean.xml.
This code is not working if I want to avoid xml configuration.
I have done those changes
bean id :loginDelegate, userService, userDao
added the #Service & #Repository annotation to the corresponding service & DAO implementation.
#Controller("loginController")
public class LoginController {
#Autowired
private LoginDelegate loginDelegate;
public LoginDelegate getLoginDelegate() {
return this.loginDelegate;
}
public void setLoginDelegate(LoginDelegate tLoginDelegate) {
this.loginDelegate = tLoginDelegate;
}
#RequestMapping(value="/login.do",method=RequestMethod.GET)
public ModelAndView displayLogin(HttpServletRequest request, HttpServletResponse response) {
log.info("<---displayLogin()--->");
ModelAndView model = new ModelAndView("login");
LoginBean loginBean = new LoginBean();
model.addObject("loginBean", loginBean);
return model;
}
}
public class LoginDelegate {
#Autowired
private IUserService userService;
public IUserService getUserService() {
return this.userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public boolean isValidUser(String username, String password) throws Exception {
return userService.isValidUser(username, password);
}
}
public interface IUserService {
public boolean isValidUser(UserBean userObj);
public int addUsers(UserBean userObj);
}
public class UserServiceImpl implements IUserService {
#Autowired
private IUserDao userDao;
public IUserDao getUserDao() {
return this.userDao;
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
public boolean isValidUser(UserBean userObj) {
return userDao.isExistUser(userObj);
}
#Override
public int addUser(final UserBean userObj) {
return userDao.saveUserDetails(userObj);
}
}
public interface IUserDao {
public boolean isExistUser(UserBean userObj);
public int saveUserDetails(UserBean userObj);
}
public class UserDaoImpl implements IUserDao {
#Autowired
UserBean userObj;
#Autowired
DataSource dataSource ;
public DataSource getDataSource(){
return this.dataSource;
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
Use Java-based configuration if you want to completely get rid of XML-based configuration
#Configuration
#ComponentScan(basePackages = "com.acme")
public class AppConfig {
...
}
The above normal Java class when annotated with #Configuration, makes it a 'Spring Configuration class' (analogous to XML-based configuration).
#ComponentScan annotation scans for classes annotated with #Component, #Controller, #Service, #Repository classes from the package defined during start-up time to get them registered as Spring beans. This can be done in XML also with <context:component-scan base-package="com.acme" />
Refer:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-java-instantiating-container-scan

How do i inject a spring bean into a hibernate SequenceGenerator

I have a custom SequenceGenerator written for hibernate:
public class LoginGenerator extends SequenceGenerator {
#Autowired
ITicketService ticketService;
#Override
public Serializable generate(SessionImplementor session, Object obj) {
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}
But i dont have a spring context inside this generator! ticketService is null. i already tried #Component annotation for my generator, but without success.
PS: Im using spring 3.2.0-FINAL and hibernate 3.6.10-FINAL and there is no way updating to hibernate4!
Any idea, anyone?
Problem solved with ApplicationContextAware class, as described above.
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#SuppressWarnings("static-access")
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
}
In applicationContext.xml I added <bean id="applicationContextProvider" class="de.gfz.rz.spring.ApplicationContextProvider"></bean>.
And here the usage:
public class LoginGenerator extends SequenceGenerator {
#Override
public Serializable generate(SessionImplementor session, Object obj) {
ITicketService ticketService = ApplicationContextProvider
.getBean(ITicketService.class);
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}

Resources