How to get the configuration in my Custom Annotation Processing whitch was defined in my Maven plugin - maven

My goal is read a parameter's value from costom Maven Plugin
during the processing of process, I need this value to determine whether to process annotations.
Here is what i done:
customize a maven plugin to configure the parameter of funProcess
#Mojo(defaultPhase = LifecyclePhase.COMPILE, threadSafe = true,
requiresDependencyResolution = ResolutionScope.COMPILE)
public class PamirsFunctionMojo extends AbstractMojo {
#Parameter
private Boolean funProcess;
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
//todo
this.getPluginContext().put("funProcess", funProcess);
}
}
this is my maven-plugin's definition.
<groupId>pro.xxx.pamirs.plugin</groupId>
<artifactId>pamirs-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>2.0.0-SNAPSHOT</version>
Build a project to process annotation #Fun which is defined in method. So,I need to define A Annotation Processor through extends AbstractProcessor,handle the method corresponding to this #Fun annotation in the process interface.
Using the value in my Annotation Processor.
I need the value of funProcess which is configured within the pom of business project which relying on this Annotation Processor project, then using the value to determine whether to process annotations In the Annotation Processor project.
The test project will rely on annotation processing projects and my maven-plugin.
This is the POM definition .
<dependencies>
<dependency>
<groupId>pro.xxx.pamirs.annotation</groupId>
<artifactId>annotation-processor</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>pro.xxx.pamirs.plugin</groupId>
<artifactId>pamirs-maven-plugin</artifactId>
<version>2.0.0-SNAPSHOT</version>
<executions>
<execution>
<configuration>
<funProcess>false</funProcess>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</dependency>
I want to know how to get the value in my Annotation Processor.

Related

Spring Boot With Cucumber Integration

I have been working on a spring boot application I would like to test with cucumber (for business driven development). I can successfully run the cucumber tests with my code, or I can boot the spring context, but I cannot seem to figure out a way to do both at once. I have looked around, and found a few tutorials (such as https://medium.com/#bcarunmail/set-up-and-run-cucumber-tests-in-spring-boot-application-d0c149d26220) that all seem to have this working. I followed the same premise as them, that is, (1) having one class that loads the spring context, (2) having another class be the entry point for discovering the cucumber tests, and finally, (3) a class containing the step definitions that extends the class with the context referenced in number one.
Here are my classes
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.MySQLContainer;
import com.connor.Application;
/**
* This class should take care of initializing the test container (for the database) and populating it using the
* sql files that run against the actual db, in the actual order they execute. This guarantees these will run
* before we even use a staging region. Once the database is created, it boots the spring context the spring context
* and configures the environment with the db-related info from the test container.
*
* When ran alone, this test successfully performs the above steps and can be used for integration tests.
* However, when this class is extended by other classes (the glue code classes), it does not boot the spring context
* and hence do not work for integration tests.
* #author connor
*
*/
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Application.class)
#ContextConfiguration(initializers = SpringContextConfigForCukeUsage.Initializer.class)
//#Ignore //even with this, still need a test method to compile
public /* abstract */ class SpringContextConfigForCukeUsage { //with or without abstract, this doesn't seem to work . . .
/**
* Use with String.format to build the base url string when testing locally.
*/
private static final String LOCAL_BASE_URL_FORMAT_STR = "%s:%d";
/**
* Create the mysql test container as a class rule.
*/
#ClassRule
public static MySQLContainer<?> mysqlDb = new MySQLContainer<>("mysql:latest") //TODO may not want the latest version . . .
.withInitScript("schema.sql");
/**
* The base url for the tests. By passing in here, we allow for testing actual environments, as well as integration tests with the same code.
* If no value is passed, defaults to localhost, and will be combined with port to build base url
*/
#Value("${BASE_URL:locahost}")
private String baseUrl;
/**
* For getting access to the port the spring boot context is running on in subclasses
*/
#LocalServerPort
protected int serverPort;
//Decide whether to use rest template or test res template here
/**
* Used in subclasses to get access to the base url for testing.
* #return
*/
protected String getBaseUrl() {
String baseUrlToReturn;
//if it is local, append the port
if(baseUrl != null && baseUrl.contains("localhost")){
baseUrlToReturn = String.format(LOCAL_BASE_URL_FORMAT_STR, baseUrl, serverPort);
}
//otherwise, return the environment variable, which will always be available on standard http(s) port
else {
baseUrlToReturn = baseUrl;
}
return baseUrlToReturn;
}
/**
* This initalizer class takes care of setting the properties from the test container into environment variables.
* This allows integration tests to be as close to real testing as possible.
* #author connor
*
*/
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//add the url, username, and password to the test context before it starts
TestPropertyValues.of(String.format("spring.datasource.url=%s", mysqlDb.getJdbcUrl()),
String.format("spring.datasource.username=%s", mysqlDb.getUsername()),
String.format("spring.datasource.password=%s", mysqlDb.getPassword()))
.applyTo(applicationContext.getEnvironment());
}
}
/**
* This method is only here to test when running alone for debugging . . .
*/
#Test
public void test() {
//just here for compilation when testing this class by itself-- will not execute if no test here
}
}
Here is the second class, the one with the entry point for the cucumber tests
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
/**
* This is the entry point for running the cucumber tests.
* #author connor
*
*/
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/it/resources/AddingAssessment.feature")
public class RunCukesIT {
//intentionally blank -- annotations do all the work
}
Finally, here is my third class containing my step definitions:
import cucumber.api.java8.En;
/**
* This class contains the glue code for the "given when then" step definitions.
* This extends the class that bots the spring context, but it does not boot the
* context
* #author connor
*
*/
//even with these annotations, it does not load spring boot context
//#RunWith(SpringRunner.class)
//#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Application.class)
//#ContextConfiguration(initializers = SpringContextConfigForCukeUsage.Initializer.class)
public class CukeGWT extends SpringContextConfigForCukeUsage implements En {
public CukeGWT() {
Given("we are attempting to add a test for a book", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n" + serverPort); //always 0 (because context doesn't load)
//
System.out.println("Env property is " + System.getenv("local.server.port")); //this also indicates server doesn't start
});
Given("the book has isbn {int}", (Integer int1) -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the author of the book has first name conn", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the author of the book has last name b", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the book has {int} questions", (Integer int1) -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("one of the questions has incorrect answers a hen, a cat", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the question has correct answer a dog", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
When("the api is called", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the api will return a valid response", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the isbn will match", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the author's first name will match", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the author's last name will match", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the question added above will exist", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the book will be unverified", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the author of the book has first name test", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the author of the book has last name testing", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("one of the questions has incorrect answers true", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("the question has correct answer false", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Given("an assessment with valid data is generated", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the api will return an error response", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the http status code will be {int}", (Integer int1) -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
Then("the error message will contain A test already exists for this book", () -> {
// Write code here that turns the phrase above into concrete actions
//throw new cucumber.api.PendingException();
});
}
}
Here is my pom for reference of the dependencies/versions
<?xml version="1.0" encoding="UTF-8"?>
https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
com.connor
reading-comprehension-api
0.0.1-SNAPSHOT
reading-comprehension-api
This is the containerized webservice for reading
comprehension
<properties>
<!-- miscellaneous properties -->
<docker.image.prefix>connordocker</docker.image.prefix>
<java.version>1.8</java.version>
<!-- get as much info as we can locally for development -->
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<!-- versions, please keep in alphabetical order -->
<cucumber.version>4.2.5</cucumber.version>
<testcontainer.version>1.12.4</testcontainer.version>
</properties>
<dependencies>
<!-- bring this in once database is integrated and defined in properties
file -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- lets us connect to mysql db -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- lets us use test containers; must use same version as mysql test container
below -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainer.version}</version>
<scope>test</scope>
</dependency>
<!-- mysql specific test container; must use same version as testcontainers -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>${testcontainer.version}</version>
<scope>test</scope>
</dependency>
<!-- the below three dependencies are required for cucumber tests -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java8</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- create different profiles for each ci/cd stage -->
<profiles>
<!-- this is ran for every commit -->
<profile>
<id>commit-profile</id>
<activation>
<!-- if we make this active by default, it runs, even when we explicitly
mention another profile -->
<!-- active by default -->
<!-- <activeByDefault>true</activeByDefault> -->
</activation>
<build>
<!-- TODO add compile plugin, surefire plugin here -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<!-- inherit surefire plugin for running unit tests. Overwrite and add
additional configuration to ignore our integration tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- ignore the integration tests (named *IT) which come from src/it/java,
but are placed on classpath by the build helper plugin (IT must be on test
classpath to run, but we don't want them running here) -->
<excludes>
<exclude>**/*IT.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- this is ran on the merge to master -->
<profile>
<id>merge-to-base-branch-profile</id>
<!-- active when stage is merge -Dstage=merge -->
<activation>
<property>
<name>stage</name>
<value>merge</value>
</property>
</activation>
<!-- TODO add enforcer plugin, failsafe plugin, codehaus plugin -->
</profile>
<!-- this is ran and triggered by a tag -->
<profile>
<id>deploy-profile</id>
<!-- active when stage is deploy -Dstage=deploy, should be triggered by
tag from pipeline -->
<activation>
<property>
<name>stage</name>
<value>deploy</value>
</property>
</activation>
<!-- not sure if we want to (or can) trigger deployment to cloud from
maven, or if we can -->
</profile>
<!-- this profile is triggered for running integration tests -->
<profile>
<id>integration-test-profile</id>
<!-- make to skip unit tests so we don't get confused -->
<properties>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<!-- this plugin adds folders to the classpath. As of right now, it
takes care of adding the integration tests (and feature files) to test classpath. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<!-- this execution adds the src/it/java to test classpath -->
<execution>
<id>add-integration-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
<!-- this execution adds the src/it/resources to test classpath -->
<execution>
<id>add-integration-test-resource</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/it/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- this runs the integration tests -->
<!-- NOTE: I have been considering using this for e2e tests once deployment
is done to staging region. This would allow us to reuse code, with the only
change being the base url system property passed in. However, we still have
to deal with populating the region database, and the fact we want our integration
tests to be much more extensive than our e2e tests, which should be very
brief -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>integration-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<!-- this is needed so we can skip unit tests here, but not integration tests (as both default to skip tests property, which we set to true to ignore unit tests) -->
<skipTests>false</skipTests> <!-- NOTE: In future here, could configure with ${skip.failsafe.tests} or any other variable but skip tests -->
<!-- only run integration tests, which should end in IT -->
<includes>
<include>**/*IT.java</include>
</includes>
<excludes>
<exclude>**/*Test.java</exclude>
</excludes>
<!-- set the environment variable from what is passed in as a system
variable. This allows use with spring boot property injection NOTE: there
is no need to set the jdbc related info here, this comes from test container -->
<environmentVariables>
<!-- set the base url; if not set defaults to localhost for int
testing -->
<BASE_URL>${BASE_URL}</BASE_URL>
</environmentVariables>
</configuration>
</execution>
</executions>
</plugin>
<!-- this plugin builds a pretty(ier) html report from the results of
cucumber tests. This should only be active in this profile, after int tests
have ran -->
<plugin>
<groupId>net.masterthought</groupId>
<artifactId>maven-cucumber-reporting</artifactId>
<version>2.8.0</version>
<!-- we have one execution tag per functionality exposed by the api -->
<executions>
<!-- for the add integration tests -->
<execution>
<id>addCucumberReport</id>
<phase>verify</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<projectName>CucumberWebGui</projectName>
<outputDirectory>${project.build.directory}/cucumber-report-html/add</outputDirectory>
<cucumberOutput>${project.build.directory}/cucumber-report/addCucumber.json</cucumberOutput>
</configuration>
</execution>
<!-- for get integration tests -->
<execution>
<id>getCucumberReport</id>
<phase>verify</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<projectName>CucumberWebGui</projectName>
<outputDirectory>${project.build.directory}/cucumber-report-html/get</outputDirectory>
<cucumberOutput>${project.build.directory}/cucumber-report/getCucumber.json</cucumberOutput>
</configuration>
</execution>
<!-- for the verify/udpate reports -->
<execution>
<id>updateCucumberReport</id>
<phase>verify</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<projectName>CucumberWebGui</projectName>
<outputDirectory>${project.build.directory}/cucumber-report-html/update</outputDirectory>
<cucumberOutput>${project.build.directory}/cucumber-report/verifyCucumber.json</cucumberOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<!-- NOTE: this is the build tag. Every plugin specified here will always
run, regardless of if a profile is selected, or if there are multiple profiles
selected. -->
<build>
<plugins>
<!-- This is the default spring boot plugin that wraps as jar and allows
running with embedded instance -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- display active profile in compile phase -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<executions>
<execution>
<id>show-profiles</id>
<phase>compile</phase>
<goals>
<goal>active-profiles</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The source code for this can be found at: https://gitlab.com/connorbutch/reading-comprehension-api

What is the appropriate driver to load for embedded DynamoDB in a Spring app?

I followed various tutorials to end up with the configuration below. There may also be incorrect configuration causing the problem. When I run the tests, I get:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.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 (the profiles "test" are currently active).
Research has lead me to believe that the appropriate driver is not being loaded and I have to add it to .properties. Is that something included in DynamoDBLocal library? I can't find it in the docs and it seems my only option is to get a 3rd party driver from the web.
Here's are the important parts:
pom.xml:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.11.34</version>
</dependency>
<dependency>
<groupId>com.github.derjust</groupId>
<artifactId>spring-data-dynamodb</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>DynamoDBLocal</artifactId>
<version>1.10.5.1</version>
</dependency>
DataSourceConfigLocal:
#Configuration
#EnableWebMvc
#EnableDynamoDBRepositories(basePackages="com.cfa.dao")
#Profile({"local", "test"})
public class DataSourceConfigLocal {
#Value("${amazon.dynamodb.endpoint}")
private String amazonDynamoDBEndpoint;
#Value("${amazon.aws.accesskey}")
private String amazonAWSAccessKey;
#Value("${amazon.aws.secretkey}")
private String amazonAWSSecretKey;
#Bean
public AmazonDynamoDB amazonDynamoDB() {
AmazonDynamoDB amazonDynamoDB
= new AmazonDynamoDBClient(amazonAWSCredentials());
if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) {
amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint);
}
return amazonDynamoDB;
}
#Bean
public AWSCredentials amazonAWSCredentials() {
return new BasicAWSCredentials(
amazonAWSAccessKey, amazonAWSSecretKey);
}
}
IntegrationTest:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#Profile("test")
#TestPropertySource(properties = {
"amazon.dynamodb.endpoint=http://localhost:8000/",
"amazon.aws.accesskey=x",
"amazon.aws.secretkey=x" })
public class OrderRequestRepositoryIntegrationTest {
private DynamoDBMapper dynamoDBMapper;
#Autowired
private AmazonDynamoDB amazonDynamoDB;
#Autowired
OrderRequestDao orderRequestDao;
private static final String STORE_NUMBER = "100";
#Before
public void setup() throws Exception {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper
.generateCreateTableRequest(OrderRequest.class);
tableRequest.setProvisionedThroughput(
new ProvisionedThroughput(1L, 1L));
amazonDynamoDB.createTable(tableRequest);
dynamoDBMapper.batchDelete(
(List<OrderRequest>)orderRequestDao.findAll());
}
#Test
public void sampleTestCase() {
OrderRequest orderRequest = new OrderRequest(STORE_NUMBER);
orderRequestDao.save(orderRequest);
List<OrderRequest> result
= (List<OrderRequest>) orderRequestDao.findAll();
assertTrue("Not empty", result.size() > 0);
assertTrue("Contains item with expected cost",
result.get(0).getStoreNumber().equals(STORE_NUMBER));
}
}
I am not sure whether you have already referred this. I am adding this as it may help you.
Test using HTTP and without using HTTP
pom file which has the server runner and sql lite
1) Also, use the latest version 1.11.0.1 of the JAR.
2) SQL Lite lib in classpath
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>DynamoDBLocal</artifactId>
<version>${aws.dynamodblocal.version}</version>
</dependency>
<profile>
<id>start-dynamodb-local</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec.maven.plugin.version}</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<executable>java</executable>
<arguments>
<argument>-cp</argument>
<classpath/>
<argument>-Dsqlite4java.library.path=${basedir}/target/dependencies</argument>
<argument>com.amazonaws.services.dynamodbv2.local.main.ServerRunner</argument>
<argument>-inMemory</argument>
<argument>-port</argument>
<argument>${dynamodb-local.port}</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

Jigsaw test dependencies in classpath: why is the superclass in another JAR not accessible?

I am currently testing to migrate an existing Java 8 (Maven) project to Java 9 / Jigsaw, using jdk9-ea+147 and maven-compiler-plugin 3.6.0.
I have converted the src directory to a module and left the test directory non-modular.
During testCompile I get an unexpected error:
error: build() in ExtractedArtifactStoreBuilder is defined in an inaccessible class or interface
Of course I have checked that both the ExtractedArtifactStoreBuilder is public. build() is inherited from its (public) superclass and public as well. The code compiles and runs fine in JDK 8.
ExtractArtifactStoreBuilder is defined in a different 3rd partry JAR than its superclass, but Maven correctly puts both in the classpath. Confusingly, the superclass has the same classname (but resides in a different package)
As far as I can see, I should be able to access public inherited methods in my test code. So is this a bug in the jdk9 early access version?
Edit: hoping for better comprehensibility, here is a little abstraction of the involved JARs and classes, with less confusing naming and unimportant stuff left out (for the actual dependencies, see below):
process.jar
public ProcessStoreBuilder
public ProcessStoreBuilder download(...) // returns "this"
public ... build()
mongo.jar
public MongoStoreBuilder extends ProcessStoreBuilder
src/test/java/ExampleTest
mongoStoreBuilder.download(...).build()
// ^ breaks at compile time, saying that
// ProcessStoreBuilder#build() is not accessible
I have been able to reproduce the behavior in a minimal setup:
pom.xml (excerpt)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>9</source>
<target>9</target>
<debug>true</debug>
<optimize>true</optimize>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>1.50.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.process</artifactId>
<version>1.50.0</version>
<scope>test</scope>
</dependency>
</dependencies>
src/main/java/module-info.java
module com.mycompany.example.testdependencyexample {}
src/test/java/ExampleTest.java (excerpt)
#Before
public void setUp() throws Exception {
// both `download` and `build` are inherited from the superclass
// the following does work
// de.flapdoodle.embed.mongo.config.ExtractedArtifactStoreBuilder
ExtractedArtifactStoreBuilder easb = new ExtractedArtifactStoreBuilder();
easb.download(new DownloadConfigBuilder().build());
easb.build();
// but this does not
// download returns the same instance but has the superclass as return type
// de.flapdoodle.embed.process.store.ExtractedArtifactStoreBuilder
// the compiler can't see the `build` method of the superclass
new ExtractedArtifactStoreBuilder()
.download(new DownloadConfigBuilder().build())
.build();
}

Binding with #Autowired not working inside instances initiated with 'new'

In my web spring application I create an instance with key word new as following.
In my one of action class, following method exists.
public void process() {
MyBean b=new MyBean(); //initiated the instance with new
b.process();
}
Other MyBean class
#Service
public class MyBean {
#Autowired
MyService service;
public void process() {
service.execute(); // this service instance has not initialized by Spring DI :( .service object is null.
}
the MyService instance is not set by spring Dependency injection. Is it because that I create the instance of MyBean myself with new not the Spring ?
If you want to autowire programmatically, you can use:
private #Autowired AutowireCapableBeanFactory beanFactory;
public void process() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}
Yes. It is not being set by DI of Spring as the instance you created using new keyword is not being managed by Spring container. Spring will by default inject dependencies only for spring managed instances. So to resolve this problem you can do it by two ways. First is don't use the new and use #Autowired on Mybean instance.
Second is to use #Configurable on MyBean class. With the #Configurable annotation spring will inject dependencies even for objects created through new keyword. Remember to have AspectJ jars on your classpath with #configurable annotation as Spring need them to inject Dependecies.
For the second approach use #Configurable(preConstruction = true) and add the following dependencies to your pom.xml
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.1.RELEASE</version>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.8</version>
</dependency>
You also need to compile it through AspectJ Compiler so that Byte code generated has the required abilities. You should use the following entries to make sure system using AspectJ Compiler at compile time.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>1.6</source>
<target>1.6</target>
<Xlint>ignore</Xlint>
<complianceLevel>1.6</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>false</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.11</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
When you create an object by new, autowire\inject don't work...
as workaround you can try this:
create your template bean of MyBean
<bean id="myBean" class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
and create an istance in this way
context.getBean("myBean");
PROTOTYPE : This scopes a single bean definition to have any number of object instances.
In your case, spring does not recognize MyBean bean because you are creating it with new operator. Let spring initialize this bean and then you can have autowired beans accessed inside MyBean. For e.g.
<bean id="myBean" class="your.package.MyBean"></bean>
Above entry in your application context will create MyBean in spring container. And using this object you can access the services written inside it.
Another solution can be the use of #Component like this:
#Component("myBean")
public class MyBean{
#Autowired
MyService service;
public void process(){
service.execute(); // this service instance has not initialized by Spring DI :( .service object is null.
}
}
And at your class where process() is, you can Autowire like this:
#Autowired
MyBean b
public void process(){
b.process();
}

Maven mojo not picking up configuration from pom

I've written a Maven plugin and incorporated it as a goal in the package phase of another project with configuration given in that project's pom.xml. However, none of the fields set using the #parameter notation end up being populated so they just throw NullPointerExceptions when they get used.
My mojo:
/**
* #goal wrap
* #phase package
*/
public class MyMojo extends AbstractMojo {
/**
* #parameter expression="${project.build.directory}"
*/
private String outputDirectory;
/**
* #parameter
*/
private String dbDataName;
private File dbFile;
public MyMojo(){
dbFile = new File(outputDirectory, dbDataName) // throws nullpointerexception
}
public void execute() throws MojoExecutionException{
// Do stuff
}
}
Some of the mojo pom:
<groupId>com.mycompany.wrapper</groupId>
<artifactId>something-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.2</version>
<configuration>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The relevant bit of my project pom:
<plugin>
<groupId>com.mycompany.wrapper</groupId>
<artifactId>something-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>wrap</goal>
</goals>
<configuration>
<dbDataName>dcbTestData.sql</dbDataName>
</configuration>
</execution>
</executions>
</plugin>
Can anyone see what I'm doing wrong here? Most likely it's some silly mistake that I'm just not seeing.
I've solved the problem. I had done a few things wrong but after changing and tinkering, I managed to work it out.
Incidentally, this process was made rather harder by the fact that the Maven docs and user guides are a bit inconsistent about whether they prefer the annotations or the javadocs styles, and in some places they recommend deprecated methods, such as the expression="${stuff}" form.
Anyway to get it working:
I corrected the mistakes pointed out by khmarbaise in his first comment where I had slightly mangled the maven-plugin-plugin definition in my pom.
I updated to the Java annotations based way of denoting Mojos and parameters (it might have worked if I had done step 3 without doing this step, but it still seemed a good idea to update)
The main problem was that I was trying to access the parameter variables in the constructor to assign values to other variables but the mojo doesn't pick up the configuration details until the execute() method is run. So I just moved any variable assignments that used the parameters to the start of the execute() method and then they worked.
So here's what my mojo looks like now:
#Mojo(name = "wrap", defaultPhase = LifecyclePhase.PACKAGE)
public class MyMojo extends AbstractMojo {
#Parameter(property="project.build.directory")
private File outputDirectory;
#Parameter(property="dbDataName")
private String dbDataName;
private File dbFile;
public void execute()
throws MojoExecutionException {
dbFile = new File(outputDirectory, dbDataName);
// Do other stuff
}
}
You should change your code like the following:
/**
* #parameter default-value="${project.build.directory}"
*/
private String outputDirectory;

Resources