How to backport `ObjectFactory.namedDomainObjectList(...)` to gradle (5.6.4) - gradle

Working on a gradle-plugin. And i've tried to backport the functionality from gradle 6 ObjectFactory.namedDomainObjectList​(Class<T> elementType) to gradle 5.6.4.
I'v tried this with no luck:
import org.gradle.testfixtures.ProjectBuilder
import org.gradle.api.internal.CollectionCallbackActionDecorator
import org.gradle.api.internal.DefaultDomainObjectCollection
def main() {
def project = ProjectBuilder.builder().build();
CollectionCallbackActionDecorator ccad;
def myList = project.objects.newInstance(DefaultDomainObjectCollection.class,
MyClass.class,
new ListElementSource(),
ccad);
}
static class MyClass implements Named {
#Override
String getName() {
return "foobar"
}
}
Exception Stack
org.gradle.api.reflect.ObjectInstantiationException: Could not create an instance of type org.gradle.api.internal.DefaultDomainObjectCollection.
at org.gradle.internal.instantiation.DependencyInjectingInstantiator.newInstance(DependencyInjectingInstantiator.java:54)
at org.gradle.api.internal.model.DefaultObjectFactory.newInstance(DefaultObjectFactory.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:190)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:55)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:151)
github: Source of gradle instantiation

Solved it this way:
def myList = new DefaultNamedDomainObjectList(
MyClass.class,
new Instantiator() {
#Override
def <T> T newInstance(Class<? extends T> aClass, Object... objects) throws ObjectInstantiationException {
project.objects.newInstance(aClass, objects)
}
},
new DynamicPropertyNamer())

Related

Swagger codegen - change api and controller class name

I am trying to generate rest code for spring using swagger. Currently generate api is V10Api.java and controller is V10ApiController.java. I want to have custom prefix as 'ReadApi.java' and 'ReadApiController.java'.
I looked at the solution here to implement this, so my code was:
public class ReadApiSpringCodeGen extends SpringCodegen
{
static {
PREFIX="Read"; //compile error at PREFIX
}
}
it gives compilation error at PREFIX so i am guessing PREFIX is not in superclass.
I modified the class to over toApiName() method:
public class ReadApiSpringCodeGen extends SpringCodegen
{
#Override
public String toApiName(String name) {
System.out.println("Name in is ["+name+"]");
if (name.length() == 0) {
return "DefaultApi";
}
name = sanitizeName(name);
return camelize(name) + "Read";
}
public static void main(String[] args)
{
System.out.println("Main called");
}
}
When ran the code generator as:
${JAVA_HOME}/bin/java -cp .:./swagger-codegen-cli-2.2.1.jar \
-jar swagger-codegen-cli-2.2.1.jar generate \
-i Read.yaml \
-l com.foo.swag.codegen.swagger.ReadApiSpringCodeGen \
....
I get the error:
Exception in thread "main" java.lang.RuntimeException: Can't load config class with name com.foo.swag.codegen.swagger.ReadApiSpringCodeGen Available: android
ndroid
aspnet5
async-scala
cwiki
csharp
cpprest
.....
at io.swagger.codegen.CodegenConfigLoader.forName(CodegenConfigLoader.java:31)
at io.swagger.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:353)
at io.swagger.codegen.cmd.Generate.run(Generate.java:221)
at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:36)
Caused by: java.lang.ClassNotFoundException: com.foo.swag.codegen.swagger.ReadApiSpringCodeGen
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at io.swagger.codegen.CodegenConfigLoader.forName(CodegenConfigLoader.java:29)
... 3 more
You have to override method apiFilename - something like this:
#Override
public String apiFilename(final String templateName, final String tag) {
final String pathWithFile = super.apiFilename(templateName, tag);
final String pathWithoutFileExtension = pathWithFile.substring(0, pathWithFile.lastIndexOf('.')); //without .java
final int index = pathWithoutFileExtension.lastIndexOf('.');
final String className = ".Read" + pathWithoutFileExtension.substring(index+1) + ".java";
result pathWithoutFileExtension.substring(0, pathWithoutFileExtension.lastIndexOf('.')) + className;
}
I fixed it by extending SpringCodegen class and overriding toApiName() method.
public class ReadApiSpringCodeGen extends SpringCodegen
{
#Override
public String toApiName(String name) {
return "CustomReadApi";
}
}
Works perfectly. Thanks for all the clues.

Drive V3 API : java.lang.IllegalArgumentException

This is how I create "AbstractInputStreamContent" from inputstream of file:
final Long length = Long.valueOf(filesData.get(uploadedFileName).get("size")).longValue();
final InputStream fileStream = item.openStream(); //FileItemStream item
AbstractInputStreamContent fileContent = new AbstractInputStreamContent(uploadedFileMimeType) {
#Override
public boolean retrySupported() {
return false;
}
#Override
public long getLength() throws IOException {
return length;
}
#Override
public InputStream getInputStream() throws IOException {
return fileStream;
}
};
And "InputStreamContent" as:
InputStreamContent fileContent = new InputStreamContent(uploadedFileMimeType, item.openStream());
fileContent.setLength(Long.valueOf(filesData.get(uploadedFileName).get("size")).longValue());
To replace old file with new file I use(both files are of .docx format):
Drive.Files.Update update = driveService.files().update(fileIdOfFileToReplace,fileMeta,fileContent);
update.set("uploadType", "resumable");
update.getMediaHttpUploader().setDirectUploadEnabled(false);
update.getMediaHttpUploader().setChunkSize(MediaHttpUploader.DEFAULT_CHUNK_SIZE);
File updatedFile = update.execute();
Uploading a new file works fine whether I use InputStreamContent or AbstractInputStreamContent. But update gives "java.lang.IllegalArgumentException" with both
java.lang.IllegalArgumentException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:111)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.googleapis.media.MediaHttpUploader.setInitiationRequestMethod(MediaHttpUploader.java:872)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.initializeMediaUpload(AbstractGoogleClientRequest.java:237)
at com.google.api.services.drive.Drive$Files$Update.<init>(Drive.java:3163)
at com.google.api.services.drive.Drive$Files.update(Drive.java:3113)
at com.util.DocumentsUtil.updateFile(DocumentsUtil.java:22)
at com.controllers.collab.documents.Documents.fileUpload(Documents.java:165)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:44)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
Solved it by giving exclusion of google-api-client from each google api maven dependency. Later added google-api-client-1.22.0-SNAPSHOT dependency from sonatype repo. It works fine

Exception accessing Spring managed bean from Groovy closure

I have a simple Spring Boot application with 2 bean classes, a main class and a configuration class. Whenever I try to access the Spring managed Bank bean from a Groovy closure, I get an exception:
Exception in thread "main" java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:304)
at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:675)
at com.example.closures.ClosuresApplication$_run_closure1.doCall(ClosuresApplication.groovy:22)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:690)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.boot.SpringApplication$run.call(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292)
at com.example.closures.ClosuresApplication.main(ClosuresApplication.groovy:27)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
Caused by: groovy.lang.MissingPropertyException: No such property: bank for class: com.example.closures.ClosuresApplication$$EnhancerBySpringCGLIB$$44735576
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:439)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2027)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:51)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2012)
at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2053)
at org.codehaus.groovy.runtime.dgm$162.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:304)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
at com.example.closures.ClosuresApplication$_run_closure1.doCall(ClosuresApplication.groovy:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:122)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.example.closures.ClosuresApplication.run(ClosuresApplication.groovy:21)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:672)
... 9 common frames omitted
Bank.groovy
#Component
final class Bank {
final String name = 'MyBank'
final AutomatedTellerMachine insideAtm
final AutomatedTellerMachine outsideAtm
#Autowired
Bank(#Qualifier('insideAtm') final AutomatedTellerMachine insideAtm, #Qualifier('outsideAtm') final AutomatedTellerMachine outsideAtm) {
this.insideAtm = insideAtm
this.outsideAtm = outsideAtm
}
String getName() {
return name
}
AutomatedTellerMachine getInsideAtm() {
return insideAtm
}
AutomatedTellerMachine getOutsideAtm() {
return outsideAtm
}
}
AutomatedTellerMachine.groovy
final class AutomatedTellerMachine {
final String name
AutomatedTellerMachine(final String name) {
this.name = name
}
String getName() {
return name
}
}
AppConfig.groovy
#Configuration
class AppConfig {
#Bean(name = 'insideAtm')
AutomatedTellerMachine getInsideAtm() {
new AutomatedTellerMachine('insideAtm')
}
#Bean(name = 'outsideAtm')
AutomatedTellerMachine getOutsideAtm() {
new AutomatedTellerMachine('outsideAtm')
}
}
ClosuresApplication.groovy
#SpringBootApplication
class ClosuresApplication implements CommandLineRunner {
#Autowired
private Bank bank
#Override
void run(String... args) throws Exception {
for (def i = 0; i < 10; i++) {
printf 'Bank %02d: %s%n', (i + 1), bank
}
(1..10).each {
printf 'Bank %02d: %s%n', it, bank
}
}
static void main(String[] args) {
SpringApplication.run ClosuresApplication, args
}
}
The regular for loop works just fine, but the .each {} closure from Groovy gives an exception. Any ideas?
I have run into this problem at odd times and found that a simple work-around can fix it - add a reference to your bank variable in the run method:
def _bank = bank
(1..10).each {
printf 'Bank %02d: %s%n', it, _bank
}
It seems to be an odd scoping issue that I have never been able to determine the real cause of.
Another possible solution is converting bank field to groovy property by removing 'private' modifier.
#Autowired
Bank bank
This is slightly less visually hideous (especially if you having this issue with more than one field), but it does change access level of that field.
I've encountered a number of these issues, all seemingly related to using private fields inside various closures in spring-managed beans, specifically when the beans are 'enhanced' (proxied) by spring (EnhancerBySpringCGLIB).

Camel's BridgePropertyPlaceholderConfigurer is not working when using Java config

I'm using Spring Java config and writing a console application with a few Camel routes. I have several properties sources in my app, so I use two PropertyPlaceholderConfigurers:
#Configuration
#Import(CamelConfig.class)
#ComponentScan(basePackageClasses = {App.class})
public class Config
{
final static String ENV = System.getProperty( "ENV" );
#Bean
public static BridgePropertyPlaceholderConfigurer properties()
{
final BridgePropertyPlaceholderConfigurer result = new BridgePropertyPlaceholderConfigurer();
result.setOrder( 0 );
result.setIgnoreUnresolvablePlaceholders( true );
result.setLocations( new ClassPathResource( "a/b/c/environments/base.properties" ),
new ClassPathResource( "a/b/c/environments/" + ENV + "/env.properties" ) );
return result;
}
#Bean
public static BridgePropertyPlaceholderConfigurer dlqAppProperties()
{
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
final BridgePropertyPlaceholderConfigurer result = new BridgePropertyPlaceholderConfigurer();
yaml.setResources( new ClassPathResource( "app.yaml" ) );
result.setOrder( 1 );
result.setIgnoreUnresolvablePlaceholders( true );
result.setProperties( yaml.getObject() );
return result;
}
}
As per this doc I'm using BridgePropertyPlaceholderConfigurer class to make Spring properties available in Camel. It's config is simple too:
#Configuration
public class CamelConfig extends SingleRouteCamelConfiguration
{
#Override
protected CamelContext createCamelContext() throws Exception
{
final SpringCamelContext result = new SpringCamelContext( getApplicationContext() );
return result;
}
#Override
protected void setupCamelContext( CamelContext camelContext ) throws Exception
{
}
#Bean
#Override
public RouteBuilder route()
{
return (new Routes()).builder();
}
}
Test route (Scala DSL) is simple too:
class Routes extends RouteBuilder {
"timer://{{foo}}?period=2s" ==> {
process((exchange) => {
exchange.getIn.setBody("test")
})
to("log:test")
}
}
But the context does not start with following exception:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'camelContext' defined in class path resource [a/b/c/config/CamelConfig.class]: Invocation of init method failed; nested exception is org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[[From[timer://{{foo}}?period=2s]] -> [process[... because of Failed to resolve endpoint: timer://{{foo}}?period=2s due to: PropertiesComponent with name properties must be defined in CamelContext to support property placeholders.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at a.b.c.App.main(App.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[[From[timer://{{foo}}?period=2s]] -> [process[... because of Failed to resolve endpoint: timer://{{foo}}?period=2s due to: PropertiesComponent with name properties must be defined in CamelContext to support property placeholders.
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:182)
at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:770)
at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:1914)
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1670)
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1544)
at org.apache.camel.spring.SpringCamelContext.doStart(SpringCamelContext.java:179)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1512)
at org.apache.camel.spring.SpringCamelContext.maybeStart(SpringCamelContext.java:228)
at org.apache.camel.spring.SpringCamelContext.afterPropertiesSet(SpringCamelContext.java:104)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
... 16 more
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: timer://{{foo}}?period=2s due to: PropertiesComponent with name properties must be defined in CamelContext to support property placeholders.
at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:477)
at org.apache.camel.util.CamelContextHelper.getMandatoryEndpoint(CamelContextHelper.java:63)
at org.apache.camel.model.RouteDefinition.resolveEndpoint(RouteDefinition.java:192)
at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:106)
at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:112)
at org.apache.camel.model.FromDefinition.resolveEndpoint(FromDefinition.java:72)
at org.apache.camel.impl.DefaultRouteContext.getEndpoint(DefaultRouteContext.java:88)
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:890)
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:177)
... 27 more
Caused by: java.lang.IllegalArgumentException: PropertiesComponent with name properties must be defined in CamelContext to support property placeholders.
at org.apache.camel.impl.DefaultCamelContext.resolvePropertyPlaceholders(DefaultCamelContext.java:1121)
at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:475)
... 35 more
Looks like the bridge does not work (but I definitely can use placeholders in Spring). What can be the problem?
Looks like if you want to use BridgePropertyPlaceholderConfigurer, you need to instantiate Camel contexts with CamelContextFactoryBean. It has initPropertyPlaceholder method:
#Override
protected void initPropertyPlaceholder() throws Exception {
super.initPropertyPlaceholder();
Map<String, BridgePropertyPlaceholderConfigurer> beans = applicationContext.getBeansOfType(BridgePropertyPlaceholderConfigurer.class);
if (beans.size() == 1) {
// setup properties component that uses this beans
BridgePropertyPlaceholderConfigurer configurer = beans.values().iterator().next();
String id = beans.keySet().iterator().next();
LOG.info("Bridging Camel and Spring property placeholder configurer with id: " + id);
// get properties component
PropertiesComponent pc = getContext().getComponent("properties", PropertiesComponent.class);
// replace existing resolver with us
configurer.setResolver(pc.getPropertiesResolver());
configurer.setParser(pc.getPropertiesParser());
String ref = "ref:" + id;
// use the bridge to handle the resolve and parsing
pc.setPropertiesResolver(configurer);
pc.setPropertiesParser(configurer);
// and update locations to have our as ref first
String[] locations = pc.getLocations();
String[] updatedLocations;
if (locations != null && locations.length > 0) {
updatedLocations = new String[locations.length + 1];
updatedLocations[0] = ref;
System.arraycopy(locations, 0, updatedLocations, 1, locations.length);
} else {
updatedLocations = new String[]{ref};
}
pc.setLocations(updatedLocations);
} else if (beans.size() > 1) {
LOG.warn("Cannot bridge Camel and Spring property placeholders, as exact only 1 bean of type BridgePropertyPlaceholderConfigurer"
+ " must be defined, was {} beans defined.", beans.size());
}
}
Well, the problem now is to have two bridges, but that's another story..
I had the same problem. Here's what worked for me (inspired by the initPropertyPlaceholder() method):
import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.spring.javaconfig.CamelConfiguration;
import org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer;
#Configuration
#ComponentScan
public class AwesomeConfig extends CamelConfiguration {
private static final String PROPERTIES_BEAN_NAME = "springProperties";
#Resource(name = PROPERTIES_BEAN_NAME)
private BridgePropertyPlaceholderConfigurer springProperties;
#Bean(PROPERTIES_BEAN_NAME)
public static BridgePropertyPlaceholderConfigurer springProperties() throws Exception {
BridgePropertyPlaceholderConfigurer configurer = new BridgePropertyPlaceholderConfigurer();
configurer.setSystemPropertiesMode(BridgePropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
String defaultPropertiesPath = buildProperties().getProperty("properties.path");
String propertiesPath = System.getProperty(PROPERTY_FILE_SYSTEM_PROPERTY, defaultPropertiesPath);
configurer.setLocations(new ClassPathResource("META-INF/application.properties"));
return configurer;
}
#Bean
public PropertiesComponent camelProperties() throws Exception {
PropertiesComponent camelProperties = new PropertiesComponent();
springProperties.setParser(camelProperties.getPropertiesParser());
springProperties.setResolver(camelProperties.getPropertiesResolver());
camelProperties.setSystemPropertiesMode(springProperties.getSystemPropertiesMode());
camelProperties.setPropertiesResolver(springProperties);
camelProperties.setPropertiesParser(springProperties);
camelProperties.setLocation("ref:" + PROPERTIES_BEAN_NAME);
return camelProperties;
}
#Override
protected void setupCamelContext(CamelContext camelContext) throws Exception {
camelContext.addComponent("properties", camelProperties());
}
}
And here's how I use it:
import org.apache.camel.spring.javaconfig.Main;
public class AwesomeMain extends Main {
setConfigClass(AwesomeConfig.class);
}
public static void main(String... args) throws Exception {
AwesomeMain main = new AwesomeMain();
instance = main;
main.run(args);
}
Try to rename your first BridgePropertyPlaceholderConfigurer bean (method's name in your case).
Look what I have hacked up. Haven't fully tested but wanted to share; should work with Spring 5.x. Basically copies all of the Environment to the Camel's properties, so I don't use the Camel's "bridge" at all. One thing I am not sure for today, if I have to put it into "initial" or "overiding" properties:
#Configuration
public static class CamelConfig extends CamelConfiguration {
#Autowired
private ConfigurableEnvironment environment;
#Bean
... some beans ...
//#Bean -- haven't yet found out if we need it as a bean ...
private PropertiesComponent camelProperties() throws Exception {
PropertiesComponent camelProperties = new PropertiesComponent();
// just brutally copy all the properties form environment
HashSet<String> propertyNames = new HashSet<String>(100);
for (PropertySource ps : environment.getPropertySources()) {
if (ps instanceof MapPropertySource) {
MapPropertySource mps = (MapPropertySource) ps;
propertyNames.addAll(Arrays.asList(mps.getPropertyNames()));
}
}
Properties allProps = new Properties();
for (String prop : propertyNames) {
allProps.setProperty(prop, environment.getProperty(prop));
}
camelProperties.setInitialProperties(allProps);
// TODO: check it this is better or worse
//camelProperties.setOverrideProperties(allProps);
return camelProperties;
}
#Override
protected void setupCamelContext(CamelContext camelContext) throws Exception {
... some configs. ...
camelContext.addComponent("properties", camelProperties());
}
}

SpringMVC- Mockito- Junit - NullPointerException when service class method is called from controller class

I am writing a web-application, by using spring MVC . I have made a service class to map things to and from the database using UI.
My problem is I am new to junit and mockito
when i am trying to write unit tests on Controller class, it always returns a NullPointerException. It is really annoying since I am unable to find the answer, so I hope you guys can help me out. Below I have posted my code.
My Controller class method on /update return success
#RequestMapping(value = "/update", method = RequestMethod.POST)
public String updateFormData(#ModelAttribute CRDetails certGuide,
ModelMap model) {
crService.updateCertification(certGuide);
return "success";
}
My Service class method updates mongodb with modified data
public void updateCertification(CRDetails certGuide) { String userTypeSubmitted = certGuide.getCertGuidelines().getUserType(); System.out.println("updated by " + userTypeSubmitted); Update update = new Update(); Query query = new Query(Criteria.where("cr").is("CR1"));
CRDetails details = certMongoTemplate.findOne(query, CRDetails.class,
COLLECTION_NAME); CertificateGuidelines newCertGuide = new CertificateGuidelines();
if (details != null) { newCertGuide.setCertG(certGuide.getCertGuidelines().getCertG()); if (userTypeSubmitted.equals("Certification Team")
&& userTypeSubmitted != "") {
newCertGuide.setStatus("Pending with Document Developer"); } else {
newCertGuide.setStatus("Pending with Certification Team"); } newCertGuide.setHistoryCount(++count);
// converting it into mongo document. MongoConverter converter = certMongoTemplate.getConverter(); DBObject newRec = (DBObject) converter
.convertToMongoType(newCertGuide); update.set("certGuidelines", newRec); }
System.out.println("new cert guide " + newCertGuide.getCertG() + " "
+ newCertGuide.getStatus() + " "
+ newCertGuide.getHistoryCount() + " "
+ newCertGuide.getUserType());
certMongoTemplate.updateFirst(query, update, CRDetails.class); }
My controllerTest class which return NullPointerException.
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.test.web.server.MockMvc;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.View;
import com.cerner.docworks.controller.CRController;
import com.cerner.docworks.domain.CRDetails;
import com.cerner.docworks.service.CRService;
public class CRControllerTest {
/*#Mock private CRService service;*/
#Mock View mockView;
#InjectMocks
private CRController crController;
private MockMvc mockMvc;
#Before public void setup() {
}
#Test public void testUpdate() throws Exception { // CRService service = Mockito.mock(CRService.class); CRService crService = Mockito.spy(new CRService()); ModelMap model = Mockito.mock(ModelMap.class); CRDetails certGuide = Mockito.spy(new CRDetails());
CRController controller = new CRController();
// Mockito.when(service.updateCertification(certGuide)); // Mockito.when(model.addAttribute(Matchers.eq("certGuide"),any(String.class))).thenReturn(null); // Mockito.doThrow(new RuntimeException()).when(crService).updateCertification(certGuide); Mockito.doNothing().when(crService).updateCertification(certGuide); Mockito.mockingDetails(certGuide); // Mockito.doCallRealMethod().when(crService).updateCertification(certGuide); // Mockito.(crService)).updateCertification(certGuide);; String fileName = controller.updateFormData(certGuide, model);
System.out.println(fileName); // Mockito.verify(controller).updateFormData(certGuide, model); assertEquals("success", fileName); } }
Trace:
java.lang.NullPointerException at
com.cerner.docworks.controller.CRController.updateFormData(CRController.java:81)
at
com.cerner.docworks.controller.test.CRControllerTest.testUpdate(CRControllerTest.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at
org.junit.runners.ParentRunner.run(ParentRunner.java:363) at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
FYI,
CRDetails is a pojo class with
private String id;
private String cr;
private String desc;
private CertificateGuidelines certGuidelines;
private Date dueDate;
//private String userType;
private String solutionName;
FYI,
When i am debugging the code, i found mock is setting objects to null
If i do set details manually, test case pass but, i want to use mockito.
Thanks in advance for ur help.
You need to run the test with the MockitoJUnitRunner, e.g.:
#RunWith(MockitoJUnitRunner.class)
public class CRControllerTest {
// ...
This allows #InjectMocks and #Mock to work properly. I.e. mockView will be created as a mock of View and crController will be created with relevant #Mock-annotated fields.
You can refer to the documentation to see how the mocks are injected.

Categories

Resources