I have a method bean that reads a file and returns a NullPointerException when the file doesn't exist. When I am running tests, I don't expect that file to exist so I want to mock that method bean to return a dummy response. It doesn't seem to be working however, and I'm getting an error like this:
"class":"o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext"
,"rest":"Exception encountered during context initialization -
cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'someName' defined in class path resource
[../../Someconfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [className]: Factory method 'someName' threw exception;
nested exception is java.lang.NullPointerException"}
The method looks like this:
#Bean
#Qualifier(SOME_QUALIFIER)
public className someName() {
// read file and return null exception if it doesn't exist
}
Would appreciate any ideas on fixing this.
This seems like a use case for Spring profiles.
Mark this method with a positive profile that is only active in production, or a negative profile that is only active in test:
#Bean #Profile("production")
#Qualifier(SOME_QUALIFIER)
public className someName() {
or
#Bean #Profile("!test")
#Qualifier(SOME_QUALIFIER)
public className someName() {
of course you will have to substitute a test configuration that is active for the test profile.
Related
I have a central library for certain functions and now I have trouble integrating that library.
The library is written in spring boot and contains a class: com.common.Security.
It is defined like this:
package com.common;
....
#Service
#EnableConfigurationProperties(SecurityProperties.class)
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Security {
....
}
I try to use this in another class:
package org.special;
import com.common.Security;
#Configuration
public class WebServiceConfig {
#Autowired
private Security security;
....
}
But I get some errors:
Error creating bean with name 'myController': Unsatisfied dependency expressed through field 'WebServiceclient';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'webserviceClient':
Unsatisfied dependency expressed through field 'template'; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'webServiceTemplate' defined in class path resource [org/special/WebServiceConfig.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.ws.client.core.WebServiceTemplate]: Factory method 'webServiceTemplate' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
nested exception is org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.Security': Scope 'request' is not active for the current thread;
consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found:
What can I do to fix this?
Removing the Scope was quite helpfull.
I tried this before but some of my tests failed after that. I didn't see, that this was because of missing settings in application.yaml for the tests.
They were not neccessary when scope is request.
I am trying to use an #Autowired variable in an #Configuration class, where a bean is created using #Bean in a method. However the component I need to create the bean with is null.
#Autowired
private JDAListener listener;
#Bean
public ShardManager shardManager() throws LoginException, IllegalArgumentException {
DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(this.botToken)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.setStatus(OnlineStatus.IDLE)
.setShardsTotal(this.totalShards)
.addEventListeners(Arrays.asList(this.listener)); //throws Exception
return builder.build();
}
The Exception I get is as follows:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'config':
Unsatisfied dependency expressed through field 'shardManager'; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'shardManager' defined in class path resource [dev/teamnight/nightbot/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [net.dv8tion.jda.api.sharding.ShardManager]: Circular reference involving containing bean 'config' - consider declaring the factory method as static for independence from its containing instance. Factory method 'shardManager' threw exception;
nested exception is java.lang.IllegalArgumentException: listeners may not be null
I assume the code snippet is a part of some kind of configuration (Something annotated with #Configuration or maybe even #SpringBootApplication).
In this case:
Make JDAListener be managed by Spring container as well.
Inject the instance of JDAListener bean into the shard manager by passing the parameter to the shardManager method
You will end up with the code that looks like this:
#Configuration
public class MyConfiguration {
#Bean // now jda listener is managed by spring!
public JDAListener jdaListener() {
return new JDAListener();
}
#Bean // note the parameter to the method
public ShardManager shardManager(JDAListener jdaListener) throws LoginException, IllegalArgumentException {
DefaultShardManagerBuilder builder =
DefaultShardManagerBuilder.createDefault(this.botToken)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.setStatus(OnlineStatus.IDLE)
.setShardsTotal(this.totalShards)
.addEventListeners(Arrays.asList(jdaListener)); //throws Exception
return builder.build();
}
}
I think that you're facing this issue because Spring attempted to dependency inject the bean before it injected the listener. How about you try declare JdaListener as a bean as well?
Is JDAListener is marked as #Component/ #Service or something which tells the framework that it is suppose to be treated as a bean? Also, quickly check your component scan configuration.
I have some #Component and #Resource in my SpringBoot application.
I have the right JDBC datasource, and also I have some REST services, by Jersey.
I want to test one of the services, but it will fail, it says:
Injection of autowired dependencies failed
But it does not use any component.
This is a simple test for testing db, and it is working:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
public class CommonRepositoryTest {
#Autowired
private MyRepository myRepository;
#Test
public void testDatabaseChangeLogsSize() {
int resultSize = myRepository.getTableRowSize(MyTable.TABLE_NAME);
System.out.println("MyTable result list size: "+resultSize);
assertTrue("MyTable table should has at least one row!", resultSize>0);
}
}
But this REST tester is not working:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
public class SampleResourceTest extends JerseyTest {
#Override
protected Application configure() {
ApplicationContext context = new AnnotationConfigApplicationContext(MyApplication.class);
return new ResourceConfig(SampleResource.class).property("contextConfig", context);
}
#Test
public void testSampleGet() throws Exception {
long id = 1;
String name = "name";
SampleDomainModel sampleDomainModel = new SampleDomainModel();
sampleDomainModel.setId(id);
sampleDomainModel.setName(name);
Response response = target("/sampleresource/samplepath/" + id).queryParam(name).request().get(Response.class);
SampleDomainModel responseSampleDomainModel = response.readEntity(SampleDomainModel.class);
assertEquals(sampleDomainModel.getId(), responseSampleDomainModel.getId());
}
}
As you see, it must override the configure() method from JerseyTest.
I think the problam is, that the AnnotationConfigApplicationContext cannot load anything maybe (?).
The #SpringApplicationConfiguration(classes = MyApplication.class) annotation loads the context, but the new AnnotationConfigApplicationContext(MyApplication.class) code maybe do the failure, it does not have the full context.
If I replace the code with mocking, it works (but it is not a nice way):
#Override
protected Application configure() {
ApplicationContext mockContext = Mockito.mock(ApplicationContext.class);
return new ResourceConfig(SampleResource.class).property("contextConfig", mockContext);
}
The fail message is:
2016-05-13 13:25:39.617 WARN 9832 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.myRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.422 sec <<< FAILURE! - in com.ws.server.SampleResourceTest
testSampleGetWithCorrectParameters(com.ws.server.SampleResourceTest) Time elapsed: 0.015 sec <<< ERROR!
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.MyRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.getDriverClassName(DataSourceProperties.java:180)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource(DataSourceAutoConfiguration.java:121)
How to use the SpringBoot context for this jersey test?
SImply put, you can't use both Spring's TestContext and Jersey Test Framework together. They will operate on two different ApplicationContexts. Even if you try to inject the ApplicationContext (created be the TestContext) into the test class and pass it to the ResourceConfig in the configure method, it's too late, as the injection doesn't occur until after construction, but the `configure method is called during contruction.
Forget JerseyTest and just use #WebIntegrationTest. See the sample from the spring boot project.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(SampleJerseyApplication.class)
#WebIntegrationTest(randomPort = true)
public class SampleJerseyApplicationTests {
#Value("${local.server.port}")
private int port;
In a Jersey/Boot environment, Jersey needs to run in a web app environment, and that's what the #WebIntegrationTest does.
For the client, instead of just calling target on the JerseyTest, you will just need to create the client
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:" + this.port);
Response response = target.path("/sampleresource/samplepath/" + id).request().get();
I know this should be a piece of cake but I'm just not getting anywhere.
In my Spring Boot app, in the application.yml file, I have an entry like so:
some:
constructor:
property: value
And I have a spring service (this is fake but demonstrates the problem):
package somepackage;
#Service
public class DummyService {
public DummyService(#Value("${some.constructor.property}") String path) {}
}
Startup fails, though:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dummyService' defined in file [...(the class
file)... ]: Instantiation of bean failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [somepackage.DummyService]: No default constructor found;
nested exception is java.lang.NoSuchMethodException:
somepackage.DummyService.()
How can I convince Spring that it should use the non-empty constructor, and it should get that constructor parameter from the YAML file? Note: I'm not using any XML bean config files or anything, and would prefer not to.
Just put the #Autowired annotation on your constructor.
#Autowired
public DummyService(#Value("${some.constructor.property}") String path) {}
And just in case someone else is trying to do this in Scala -- which is what I was really trying to do, but wanted to get the answer in Java before trying it with Scala -- this works:
#Service
class DummyService #Autowired()(#Value("${some.constructor.property}") val path: String) {
}
This is covered in this SO case for scala constructor autowiring.
As per the following spring doc link I can use #Async annotation to make a method call asynchronous. Can I use this facility in Grails from a java src file that I have?
[Update]
This is my java(netty) socket handler class which receives the socket packet.
public class DefaultHandler extends SimpleChannelUpstreamHandler {
private static final Logger LOG = LoggerFactory.getLogger(DefaultHandler.class);
private AggregateSocketData aggregateSocketData;
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
LOG.trace("In messageRecieved method with event: {}",e);
IEvent event = Events.dataInEvent(e.getMessage());
System.out.println(Thread.currentThread().getName());
aggregateSocketData.receiveSocketData(event);
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
LOG.error("Exception occurred in Default Handler: " ,e.getCause());
}
public AggregateSocketData getAggregateSocketData() {
return aggregateSocketData;
}
public void setAggregateSocketData(AggregateSocketData aggregateSocketData) {
this.aggregateSocketData = aggregateSocketData;
}
}
I have made it a bean in grails- conf - resources.xml
<bean id="defaultECM1240Handler" class="com.appcapture.buildingmgr.netty.DefaultHandler"
scope="prototype">
<property name="aggregateSocketData" ref="binaryDataAggregatorService"></property>
</bean>
And this is my grails service class whose method I have annotated with #Async
class BinaryDataAggregatorService implements AggregateSocketData {
def rawDataService
static transactional = true
#Async
void receiveSocketData(IEvent event) {
println Thread.currentThread().name
log.debug("Going to decode netty packet in receiveSocketData");
Map decodedPacket = decodePacket((INettyPacket)event.getSource())
def rawData = saveRawData (decodedPacket);
log.debug ("Saved raw data, id: ${rawData?.id}")
rawDataService.saveHTTPData(decodedPacket);
}
}
[Update 2] Here is the stack trace for the method call.
Here is the stack. BinaryDataAggregatorService.receiveSocketData(INettyPacket) line: 20
BinaryDataAggregatorService$$FastClassByCGLIB$$82489f62.invoke(int, Object, Object[]) line: not available
MethodProxy.invoke(Object, Object[]) line: 149
Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint() line: 688
Cglib2AopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 150
TransactionInterceptor.invoke(MethodInvocation) line: 110
Cglib2AopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 172
Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 621
BinaryDataAggregatorService$$EnhancerByCGLIB$$1c96985c.receiveSocketData(INettyPacket) line: not available
DefaultHandler.handlePacket(INettyPacket) line: 50
[Update 3]
The grails stack trace on setting the task:annotation-driven element.
011-05-26 17:38:03,109 [main] ERROR context.GrailsContextLoader - Error executing bootstraps: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: 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 $Proxy12
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: 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 $Proxy12
Thanks,
Abraham
If it is a spring bean - yes, you can. For that you have to annotate it with #Service and have a <context:component-scan base-package="com.foo.bar" />
But to make it easier, you can use a groovy class placed in the grails-app/services - it will be a spring bean automatically
In order to make #Async work, you need <task:annotation-driven/> in the xml config.
I found this while trying to do the same thing. I haven't tried it yet, but maybe it will work.
https://gist.github.com/tux2323/2758723
ETA:
I've modified my Resources.groovy file to match what I found here (http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html):
xmlns task:"http://www.springframework.org/schema/task"
task.'annotation-driven'('executor':'myExecutor')
task.'executor'('id':'myExecutor', 'pool-size':'5')
My code in the #Async annotation is still using the same thread as far as I can tell.
I've followed step from Jason H answer and it's really help me solve the issue on setting #Async for my service.
xmlns task:"http://www.springframework.org/schema/task"
task.'annotation-driven'('executor':'myUploadExecutor', 'proxy-target-class':true, 'mode':'proxy')
task.'executor'('id':'myUploadExecutor', 'pool-size':'5')
I've add this code in my resources.groovy then you can start using #Async in your code (dont forget to import org.springframework.scheduling.annotation.Async in you class),
without ('proxy-target-class':true, 'mode':'proxy') you will get an error java.lang.ClassCastException: com.sun.proxy.$Proxy is thrown when casting your "Service name".
In my case i'm using #Async running on different thread to add something into DB and if you are using #gorm.AuditStamp for your domain, Spring Security context didnt bound to new thread , you will get createdBy and updatedBy NULL .
To solve this issue i've add :
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) in my BootStrap.groovy on init .
For more information check out this site:
http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads