#EnableAspectJAutoProxy not work with proxyTargetClass=false - spring-aop

I am learning about Spring AOP at first time.
I am reading about in this sites:
Site2 and
Site1
Following this I have made the next classes
Main class:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();
MessagePrinter printer = context.getBean(MessagePrinter.class);
System.out.println(printer.getMessage());
}
}
App config class:
#Configuration
#ComponentScan("com.pjcom.springaop")
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
#PostConstruct
public void doAlert() {
System.out.println("Application done.");
}
}
Aspect class:
#Component
#Aspect
public class AspectMonitor {
#Before("execution(* com.pjcom.springaop.message.impl.MessagePrinter.getMessage(..))")
public void beforeMessagePointCut(JoinPoint joinPoint) {
System.out.println("Monitorizando Mensaje.");
}
}
And others...
Just like that app work nice, but if I put proxyTargetClass to false. Then I get the error below.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.pjcom.springaop.message.impl.MessagePrinter] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:318)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at com.pjcom.springaop.App.main(App.java:18)
Why?

#EnableAspectJAutoProxy(proxyTargetClass=false)
Indicates that JDK dynamic proxy will be created to support aspect execution on the object. And therefore as this type of proxy requires a class to implement an interface your MessagePrinter must implement some interface which declares method getMessage.
#EnableAspectJAutoProxy(proxyTargetClass=true)
On the opposite instruct to use CGLIB proxy which is able to create proxy for a class without an interface.

1> Message Printer has to be defined as a component i.e :
`
package com.pjcom.springaop.message.impl;
#Component
public class MessagePrinter{
public void getMessage(){
System.out.println("getMessage() called");
}
}`
in the same package as configuration java file if no #ComponentScan is not defined for some other packages.
2> If same type of bean class has many other dependencies then to resolve dependencies in spring Config use #Qualifier annotation.

Related

Camel-Cdi not injecting CamelContext with Registery

I am using camel-cdi and it is injecting the CamelContext, detecting all the routes in project.
But I want a CamelContext with a registry because I have some components that I use in camel routes like shown below.
SimpleRegistry registry = new SimpleRegistry();
registry.put("actionProcessor", actionProcessor);
registry.put("jpa", jpaComponent);
registry.put("jtaTransactionManager", platformTransactionManager);
CamelContext camelContext = new DefaultCamelContext(registry);
When I inject CamelContext the components like actionProcess, jpa are not recognized. when in my Route I have
.to("bean:actionProcessor?method=myMethod(${body})")
but my bean does not get executed.
I documentation I read use # before components name which are in registry but still it is not working.
Please suggest how can I achieve this using camel-cdi.
Did you already try with creating a CdiCamelContext (a subclass of DefaultCamelContext) ?
Otherwise, a more elegant would be to annotate your various classes, eg:
#Named("actionProcessor")
public class MyActionProcessor{
...
}
We have been using this for years without any problem
public class ContextFactory {
#Produces
#ApplicationScoped
#ContextName("Demo")
static final CamelContext createContext() {
CdiCamelContext context = new CdiCamelContext();
context.setStreamCaching(true);
context.disableJMX();
return context;
}
}
#ContextName("Demo")
public class MyRouteBuilder extends RouteBuilder {
from("...")
.to("bean:actionProcessor?method=myMethod")
}
#Named("actionProcessor")
public class MyActionProcessor{
public void myMethod(#Body String body) {}
}
Of course, in order to work, you need to activate the JEE bean discovery (=add a "beans.xml" file in META-INF or WEB-INF) !

Camel SQL - Put DataSource to SimpleRegistry in Spring Boot

I am using Spring Boot to initiate a camel route that uses Camel-sql to query MySQL DB and call a REST service.
application.properties
db.driver=com.mysql.jdbc.Driver
db.url=mysql://IP:PORT/abc
db.username=abc
db.password=pwd
Application.java
public static void main(String[] args) {
SpringApplication.run(WlEventNotificationBatchApplication.class, args);
}
DataSourceConfig.java
public class DataSourceConfig {
#Value("${db.driver}")
public String dbDriver;
#Value("${db.url}")
public String dbUrl;
#Value("${db.username}")
public String dbUserName;
#Value("${db.password}")
public String dbPassword;
#Bean("dataSource")
public DataSource getConfig() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbDriver);
dataSource.setUrl(dbUrl);
dataSource.setUsername(dbUserName);
dataSource.setPassword(dbPassword);
return dataSource;
}
}
WLRouteBuilder.java
#Component
public class WLRouteBuilder extends RouteBuilder {
#Autowired
private NotificationConfig notificationConfig;
#Autowired
private DataSource dataSource;
#Override
public void configure() throws Exception {
from("direct:eventNotification")
.to("sql:"+notificationConfig.getSqlQuery()+"?dataSource="+dataSource)
.process(new RowMapper())
.log("${body}");
}
}
I see the below error when I run, found out that Camel is unable to find DataSource bean in registry. I am quite not sure how to inject "DataSource" to Registry in Spring Boot using Java DSL.
?dataSource=org.springframework.jdbc.datasource.DriverManagerDataSource%40765367 due to: No bean could be found in the registry for: org.springframework.jdbc.datasource.DriverManagerDataSource#765367 of type: javax.sql.DataSource
Its the name of the bean that Camel uses in the uri, where you refer to it using the # syntax as documented here: http://camel.apache.org/how-do-i-configure-endpoints.html (referring beans)
So something alike
.to("sql:"+notificationConfig.getSqlQuery()+"?dataSource=#dataSource"
Where dataSource is the name of the bean that creates the DataSource, which you can give another name eg
#Bean("myDataSource")
And then the Camel SQL endpoint is
.to("sql:"+notificationConfig.getSqlQuery()+"?dataSource=#myDataSource"

mockStatic: mock java.lang with PowerMock

I am trying to mock MBeanServer with Mockito, but my attempts fails.
#Test
public void testGetAllCacheProperties() {
mockStatic(ManagementFactory.class);
MBeanServer server = MBeanServerFactory.newMBeanServer();
ObjectInstance inst = server.registerMBean(new MyBeanService(), ObjectName.getInstance(SERVICE_NAME));
given(ManagementFactory.getPlatformMBeanServer()).willReturn(server);
}
I suppose to inject my mock into method that normally runs on jBoss AS 7:
#GET
public Response getAllProperties() {
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
But it fails with exception:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
JmxMBeanServer cannot be returned by getPlatformMBeanServer()
getPlatformMBeanServer() should return MBeanServer
Update
When I try
PowerMockito.doReturn(server).when(ManagementFactory.class, "getPlatformMBeanServer");
I get exception:
java.lang.LinkageError: loader constraint violation: when resolving method "java.lang.management.ManagementFactory.getPlatformMBeanServer()Ljavax/management/MBeanServer;" the class loader (instance of org/powermock/core/classloader/MockClassLoader) of the current class, my_package_for_test_class.TestClass, and the class loader (instance of <bootloader>) for the method's defining class, java/lang/management/ManagementFactory, have different Class objects for the type javax/management/MBeanServer used in the signature
There is not possible to mock static from java.lang package, since PowerMock tries to change bite code and bite code of java.lang classes
obviously protected from modifications.
There is work around suggested by Johan Haleby.
You have to create wrapper class:
public class JmxUtils {
public static MBeanServer getPlatformMbeanServer() {
return ManagementFactory.getPlatformMBeanServer();
}
}
Then test will look like this
#RunWith(PowerMockRunner.class)
#PrepareForTest(JmxUtils.class)
public class CacheControllerTest {
//.. preconditions
given(JmxUtils.getPlatformMbeanServer()).willReturn(server);

Issue with Static resources when extending Spring Boot WebMvcConfigurationSupport

I extended WebMvcConfigurationSupport to implement an api versioning scheme - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
This uses a custom handler mapping to version the api and works quite nicely.
However it also seems to disable the #EnableAutoConfiguration bean so that now static resources aren't served (as mentioned in this question Is it possible to extend WebMvcConfigurationSupport and use WebMvcAutoConfiguration?).
Ok, I thought, let's just add a resource handler to the class above - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("classpath:/public/").addResourceLocations("/");
}
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
However.. this isn't working..? I get this error when I browse to /index.html:
No mapping found for HTTP request with URI [/index.html] in DispatcherServlet with name 'dispatcherServlet'
..If I disable this class then these resources are served just fine by #EnableAutoConfiguration magic.
I've been playing with various options to serve static content having extended the WebMvcConfigurationSupport and thus far no success.
Any ideas?
I was facing the same problem and came up with a solution that just works for me. If you just want to get the resources working without worrying of repetition you can do:
#Configuration
public class StaticResourcesConfig extends WebMvcAutoConfigurationAdapter {
}
and then
#Configuration
#EnableWebMvc
#Import(StaticResourcesConfig.class)
public class WebConfig extends WebMvcConfigurationSupport {
...
}
This successfully uses the Spring Boot defaults for serving static resources, as long as you don't map /** in your controllers.

GAE - rpc and HashMap<K,V> field

I tested my gwt app in eclipse and it worked fine; Then I tried to deploy my test app to gae... That what exception I can see in gae logs after each rpc call :
java.lang.RuntimeException: java.io.NotSerializableException
... so I am still looking the reason; but there is a point which make me confused cause one of my rpc-callback objects contains HashMap as one of its fields;
public abstract class Report implements Serializable{}
public abstract class Message implements Serializable{}
public class ErrorMessage extends Message{}
public final class Error extends Report
{
private HashMap<String,ErrorMessage> msgs;//<---?
//...
public void setMsg(HashMap<String,ErrorMessage> msgs){this.msgs=msgs;}
public HashMap<String,ErrorMessage> getMsg(){return this.msgs;}
}
...So my question is...
does gae supports java.util.HashMap ? And if not what is the most optimal collections alternative?
Thanks
It might be the "ErrorMessage" object that's not serializable.

Resources