Error while connecting to AWS SQS from spring boot - spring

I am trying to integrate AWS SQS into my springboot app using spring cloud AWS, but keep getting this error(posted below), can someone help?
Here are my files.
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'simpleMessageListenerContainer' defined in
class path resource
[org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]:
Invocation of init method failed; nested exception is
java.lang.NoSuchMethodError:
com.amazonaws.http.ExecutionContext.setCredentials(Lcom/amazonaws/auth/AWSCredentials;)V
#Configuration
public class AWSConfig {
#Value("${amazon.dynamodb.endpoint}")
private String amazonDynamoDBEndpoint;
#Value("${amazon.aws.accesskey}")
private String amazonAWSAccessKey;
#Value("${amazon.aws.secretkey}")
private String amazonAWSSecretKey;
#Value("${amazon.sqs.endpoint}")
private String amazonSqsEndpoint;
#Bean
#Primary
public AmazonSQSAsyncClient amazonSQSAsyncClient() {
AmazonSQSAsyncClient amazonSQSAsyncClient = new AmazonSQSAsyncClient(amazonAWSCredentials());
if (!StringUtils.isEmpty(amazonSqsEndpoint)) {
amazonSQSAsyncClient.setEndpoint(amazonSqsEndpoint);
}
return amazonSQSAsyncClient;
}
#Bean
public AWSCredentials amazonAWSCredentials() {
return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
}
}
I am able to work with dynamodb with this but not able to connect to SQS.
I have given the correct access key, secret access key and end point in application.properties file.
#Component
#EnableSqs
public class SQSDao {
private static final Logger logger = LoggerFactory.getLogger(SQSDao.class);
private QueueMessagingTemplate queueMessagingTemplate;
#Autowired
public SQSDao(AmazonSQSAsync amazonSqs) {
this.queueMessagingTemplate = new QueueMessagingTemplate(amazonSqs);
}
public void send(String message) {
System.out.println(queueMessagingTemplate.getDefaultDestination());
queueMessagingTemplate.convertAndSend("test-queue", MessageBuilder.withPayload(message).build());
}
#SqsListener(value = "test-queue", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void receive(String message)
{
System.out.println("message: " + message);
}
}

I was facing the same issue as described. My solution requeried implement some extra methods for the Config class:
imports [...]
#Configuration
#RefreshScope
public class SpringCloudSQSConfig {
#Value("${cloud.aws.credentials.accessKeyId:default}")
private String accessKeyId;
#Value("${cloud.aws.credentials.secretKey:default}")
private String secretKey;
#Value("${cloud.aws.region.static:default}")
private String region;
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Bean
public QueueMessagingTemplate queueMessagingTemplate() {
return new QueueMessagingTemplate(amazonSQSAsync());
}
public AmazonSQSAsync amazonSQSAsync() {
return AmazonSQSAsyncClientBuilder.standard().withRegion(Regions.US_EAST_2)
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKeyId, secretKey)))
.build();
}
#Bean
public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory() {
SimpleMessageListenerContainerFactory msgListenerContainerFactory = new SimpleMessageListenerContainerFactory();
msgListenerContainerFactory.setAmazonSqs(amazonSQSAsync());
return msgListenerContainerFactory;
}
#Bean
public QueueMessageHandler queueMessageHandler() {
QueueMessageHandlerFactory queueMsgHandlerFactory = new QueueMessageHandlerFactory();
queueMsgHandlerFactory.setAmazonSqs(amazonSQSAsync());
QueueMessageHandler queueMessageHandler = queueMsgHandlerFactory.createQueueMessageHandler();
List<HandlerMethodArgumentResolver> list = new ArrayList<>();
HandlerMethodArgumentResolver resolver = new PayloadArgumentResolver(new MappingJackson2MessageConverter());
list.add(resolver);
queueMessageHandler.setArgumentResolvers(list);
return queueMessageHandler;
}
}
And for the dependencies implemented:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws-messaging</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
and adding the next property in the properties file:
spring.main.allow-bean-definition-overriding=true

I was able to fix this problem by adding the last line shown to my application.yml during local testing
spring:
autoconfigure:
exclude:
- org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration
- org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration

I resolved it by removing duplicate dependencies :
aws-xray-recorder-sdk-aws-sdk
aws-xray-recorder-sdk-aws-sdk-v2
aws-xray-recorder-sdk-aws-sdk-instrumentor
aws-xray-recorder-sdk-aws-sdk-v2-instrumentor
Before :
<!-- AWS X-Ray -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-apache-http</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-v2</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-spring</artifactId>
</dependency>
After:
<!-- AWS X-Ray -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-apache-http</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-v2</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-spring</artifactId>
</dependency>

Fixed it, apparently issue was related to dependency mix up as mentioned here

Related

Powermock calling actual private method instead of mocking

I want to mock the private method "downloadFromNexus" but instead of mocking, actual method gets called while trying to mock here PowerMockito.doReturn("").when(spy, "downloadFromNexus", "", "");
#Component(value = "DownloadXFile")
#Order(1)
#Slf4j
public class DownloadXFile implements DownloadJarFiles {
#Value("${path}")
private String path;
#Override
public void download() throws IOException {
....
downloadFromNexus(path, outputFilePath);
log.info("jar {} downloaded", jar);
}
private void downloadFromNexus(final String url, final String outputFilePath) throws IOException {
FileUtils.copyURLToFile(
new URL(url),
new File(outputFilePath),
2000,
2000);
}
}
Test
#RunWith(PowerMockRunner.class)
#PrepareForTest(DownloadXFile.class)
#SpringBootTest(classes = DownloadXFile.class)
class DownloadXTest {
#Autowired
DownloadXFile downloadXFile;
#Test
public void test() throws Exception {
final DownloadXFilespy = PowerMockito.spy(downloadXFile);
PowerMockito.doReturn("").when(spy, "downloadFromNexus", "", "");
downloadXFile.download();
PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke("downloadFromNexus");
}
}
pom.xml
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.6.6</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.0.42-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
You called downloadXFile.download(); on original object instead of the spy.

UnknownHostException in Spring Boot with Consul

I am using spring-boot-starter-parent version 2.2.2.RELEASE with spring-cloud.version Hoxton.SR1 to create 2 services : ordercreate(Supplier) and orderconsume(Consumer).
In Consul, the 2 services are up as below
I get the exception
java.net.UnknownHostException: ordercreate
when invoking the orderconsumer service as below:
http://localhost:8282/consumeOrder
Please find the code details below.Thanks for suggestions.
ordercreate
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.properties
spring.application.name=ordercreate
server.port=8181
OrderCreateController
#RestController
public class OrderCreateController {
#GetMapping("/createOrder")
public String createOrder() {
System.out.println("In Supplier...");
return "Hello consul";
}
}
For Consumer,
orderconsume
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.properties
spring.application.name=orderconsume
server.port=8282
OrderConsumeApplication
#SpringBootApplication
#EnableDiscoveryClient
public class OrderConsumeApplication {
public static void main(String[] args) {
SpringApplication.run(OrderConsumeApplication.class, args);
}
}
OrderConsumeController
#RestController
public class OrderConsumeController {
#Autowired
private RestTemplate restTemplate;
//http://localhost:8282/consumeOrder
#GetMapping(value="/consumeOrder")
public String receiveOrder() {
String uri = "http://ordercreate/createOrder";
return restTemplate.getForObject(uri, String.class);
}
#Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

Spring web app returns HTTP Status 406

I'm creating a basic spring based web app:
pom dependencies:
<properties>
<java-version>1.8</java-version>
<springframework-version>4.3.3.RELEASE</springframework-version>
<jackson-version>2.8.3</jackson-version>
<org.slf4j-version>1.7.6</org.slf4j-version>
<logback.version>1.1.7</logback.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- #Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
In order to skip the usage of web.xml I'm using WebApplicationInitializer:
public class AppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(SpringModule.class.getPackage().getName());
return context;
}
Here is my spring config class:
#Configuration
#ComponentScan(basePackages = "com.company.app")
public class SpringModule extends WebMvcConfigurerAdapter {
public SpringModule() {
super();
}
private MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
messageConverters.add(customJackson2HttpMessageConverter());
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter());
messageConverters.add(new FormHttpMessageConverter());
super.configureMessageConverters(messageConverters);
}
/*
* Configure ContentNegotiationManager
*/
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(true).defaultContentType(
MediaType.APPLICATION_JSON);
}
Here is my test controller:
#Controller
#RequestMapping(value = "/user")
public class SomeController {
#RequestMapping(value = "/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Person helloElad() {
return new Person("some name");
}
}
When testing the controller (using browser) I'm getting:
If I'm returning a plain String it works fine.
I tries to debug method configureMessageConverters and configureContentNegotiation but for some reason it never gets there (on bootstrapping), I'm not sure it is related to the problem though.
Any ideas?
HTTP 406 is an indication that your request content is not negotiated, it is probably that necessary http message converters are not found in configuration. Simple way to add basic set of message converter would be annotating your controller #EnableMvc
I had the same problem and couldn't find a solution here or elsewhere.
I also tried the advice of applying #EnableMvc on my AppConfig but that caused a different problem in which Tomcat wouldn't even successfully start up.
Eventually, I had to rewrite my AppInit class as follows:
https://github.com/viralpatel/spring4-restful-example/tree/master/src/main/java/net/viralpatel/spring/config
Now, I'm getting JSON back when I return a POJO. I don't like this fix. The code seems incomplete compared to the AppInit shown in the problem here, but I'm unstuck.

Spring boot Turbine.stream with ssl Not working

We are trying to enable https in turbine stream. And we are facing below problem:
ERROR 10644 --- [o-eventloop-3-1] r.n.p.h.s.ServerRequestResponseConverter : Invalid HTTP request recieved. Decoder error.
java.lang.IllegalArgumentException: invalid version format: ■\ᅦ:4'|"￀+￀/￀,￀0ᅩ로또ᅩ￀ ￀￀
at io.netty.handler.codec.http.HttpVersion.<init>(HttpVersion.java:130) ~[netty-codec-http-4.0.27.Final.jar!/:4.0.27.Final]
at io.netty.handler.codec.http.HttpVersion.valueOf(HttpVersion.java:84) ~[netty-codec-http-4.0.27.Final.jar!/:4.0.27.Final]
Please provide any suggestion
Thank you.
UPDATE
Do we need to enable ssl to message broker which is handling the stream
Code
#SpringBootApplication
#RestController
#EnableDiscoveryClient
#EnableTurbineStream
public class DemoHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(DemoHystrixApplication.class, args);
}
#RequestMapping(value ="/test")
public String helloHystrix() {
ObjectMapper mapper = new ObjectMapper();
String output = null;
try {
output = mapper.writeValueAsString("{ \"message\" : \"test : Welcome to test Notification Detail Page.\"}");
} catch (JsonProcessingException e) {
e.getMessage();
}
return output;
}
#RequestMapping(value ="/test2")
public String testhello() {
ObjectMapper mapper = new ObjectMapper();
String output = null;
try {
output = mapper.writeValueAsString("{ \"message\" : \"test : Welcome to test1 Page.\"}");
} catch (JsonProcessingException e) {
e.getMessage();
}
return output;
}
}
POM Dependency
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine-stream</artifactId>
<version>1.1.5.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>
</dependencies>
application.properties
server.port=8083
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.application.name=testApp
security.basic.enabled=false
eureka.client.enabled=false
server.ssl.key-store=consul.pfx
server.ssl.key-password=changeit
server.ssl.key-store-type=PKCS12
server.ssl.trust-store=root.pfx
server.ssl.trust-store-password=changeit
server.ssl.trust-store-type=PKCS12
spring.cloud.consul.discovery.scheme=https

SpringMVC Proxy issue

I have been trying to find an answer to this problem for days, and I hope someone can point me in the right direction. I have a SpringMVC app that uses Java Configuration and I was doing fine until I tried to integrate Apache-Shiro into it. I am able to build and run my tests. But my deploy fails because of Proxy/CGLIB issues.
Here is the exception I get on deploy/restart:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'menuRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy69]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:165)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1454)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
... 55 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy69]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:217)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:409)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1625)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162)
... 65 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
... 72 more
Here is my current setup:
pom.xml
<org.springframework.version>3.2.3.RELEASE</org.springframework.version>
<shiro.version>1.2.2</shiro.version>
<org.hibernate.version>4.1.7.Final</org.hibernate.version>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.3.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.3.RELEASE</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>$3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.apache.shiro</groupId>-->
<!--<artifactId>shiro-aspectj</artifactId>-->
<!--<version>${shiro.version}</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<!-- Hibernate metamodel annotation processor -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>1.1.1.Final</version>
</dependency>
...
</>
I use this web config:
public class EdmWebInitializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final String DISPATCHER_SERVLET_MAPPING = "/*";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new
AnnotationConfigWebApplicationContext();
//I have two #Configuration classes:
rootContext.register( EdmConfiguration.class, SecurityConfig.class );
// Manage the lifecycle of the root application context
servletContext.addListener( new ContextLoaderListener( rootContext ) );
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.setServletContext( servletContext );
dispatcherContext.setParent( rootContext );
// it seems I have to register the Configuration classes again or I can't #Autowire
dispatcherContext.register( EdmConfiguration.class, SecurityConfig.class );
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet( "dispatcher", new DispatcherServlet( dispatcherContext ) );
dispatcher.setLoadOnStartup( 1 );
dispatcher.addMapping( "/" );
servletContext.addFilter( "shiroFilter", new DelegatingFilterProxy( "shiroFilter", dispatcherContext ) )
.addMappingForUrlPatterns( null, false, "/*" );
}
}
Here is my primary Configuration class:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.company.product.service", "com.company.product.utility",
"com.company.product.controller", "com.company.product.utility.startup",
"com.company.product.security", "com.company.product.repository.people" })
#EnableTransactionManagement(proxyTargetClass=false)
#ImportResource({ "classpath:applicationContext.xml" })
#PropertySource({ "classpath:application.properties", "classpath:mail.properties" })
public class EdmConfiguration extends WebMvcConfigurationSupport {
#Resource
private Environment environment;
#Autowired
private org.apache.shiro.web.mgt.WebSecurityManager securityManager;
#Bean
public DataSource dataSource() {
BoneCPDataSource dataSource = new BoneCPDataSource();
dataSource.setDriverClass( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_DRIVER ) );
dataSource.setJdbcUrl( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_URL ) );
dataSource.setUsername( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_USERNAME ) );
dataSource.setPassword( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_PASSWORD ) );
return dataSource;
}
#Bean
public JpaTransactionManager transactionManager() throws ClassNotFoundException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() );
return transactionManager;
}
#Bean
public DelegatingFilterProxy springSecurityFilterChain() {
return new DelegatingFilterProxy();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource( dataSource() );
entityManagerFactoryBean.setPackagesToScan( environment
.getRequiredProperty( PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN ) );
entityManagerFactoryBean.setPersistenceProviderClass( HibernatePersistence.class );
Properties jpaProperties = new Properties();
...
entityManagerFactoryBean.setJpaProperties( jpaProperties );
return entityManagerFactoryBean;
}
#Bean
public PersistenceExceptionTranslator exTranslator() {
return new HibernateExceptionTranslator();
}
#Bean(initMethod = "init")
public StartupListener startupListener() {
return new StartupListener();
}
#Bean
public StandardPasswordEncoder encoder() {
return new org.springframework.security.crypto.password.StandardPasswordEncoder();
}
#Bean
public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean shiroFilter = new org.apache.shiro.spring.web.ShiroFilterFactoryBean();
shiroFilter.setSecurityManager( securityManager);
shiroFilter.setLoginUrl( "/login" );
shiroFilter.setUnauthorizedUrl( "/" );
return shiroFilter;
}
#Bean
#DependsOn(value = "lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
}
And here is the other Configuration class. It is the addition of this that causes the proxy issues.
#Configuration
public class SecurityConfig {
#Bean
public SaltAwareJdbcRealm saltAwareJdbcRealm() {
return new SaltAwareJdbcRealm();
}
#Bean
public WebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm( saltAwareJdbcRealm() );
return securityManager;
}
#Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setStaticMethod( "org.apache.shiro.SecurityUtils.setSecurityManager" );
methodInvokingFactoryBean.setArguments( new Object[]{ securityManager() } );
return methodInvokingFactoryBean;
}
#Bean
#DependsOn(value = "lifecycleBeanPostProcessor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authori
zationAttributeSourceAdvisor.setSecurityManager( securityManager() );
return authorizationAttributeSourceAdvisor;
}
}
the offending class is just a spring jparepository:
public interface MenuRepository extends CrudRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {
...}
I have added the #EnableTransactionManagement(proxyTargetClass=false) which I thought would address the Proxy issue but apparently isn't.
Thank you for your time in reading all this.
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
This exception indicates that, due to some misconfiguration or multiple ways of applying AOP, a proxy of a proxy is being generated. Now with JDK Dynamic Proxies this isn't a problem however with class based proxies it is. Because cglib makes the classes final (as indicated by the stacktrace).
Your configuration has multiple ways of generation proxies, #EnableTransactionManagement triggers the registration of an AutoProxyCreator already. Next you are adding another one.
The solution in this case is to remove the DefaultAdvisorAutoProxyCreator as there is already an instance registered for you. This will disable proxying a proxy.

Resources