Cannot run AspectJ CTW application in IntelliJ IDEA without Maven rebuild - spring

EDIT/UPDATE: Delegate IDE build/run actions to maven in IntelliJ settings solve the problem, but how to handle it without it?
I have the following problem:
I change something in my GetSthAspect class -> Then I run maven clean install (let's assume I have to always do clean install in my app) -> Run spring app -> And I see error:
java.lang.NoSuchMethodError: com.example.demo.aspects.GetSthAspect.aspectOf()Lcom/example/demo/aspects/GetSthAspect;
at com.example.demo.aspects.A.shouldDoSthAndCallMethodGetSth(A.java:15) ~[classes/:na]
at com.example.demo.aspects.AspectApp.main(AspectApp.java:18) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.10.jar:5.3.10]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.10.jar:5.3.10]
...
Then I stop app -> Again do maven clean install -> Again run app and now everything works fine.
It's always like that when I change something in my GetSthAspect class and I want to see my changes in app. Why is that? Why I have to build app -> run app -> stop app -> again build app and run it in order to my aspects works fine? What should I do to avoid this situation?
GetSthAspect
#Aspect
public class GetSthAspect {
Logger logger = LoggerFactory.getLogger(GetSthAspect.class);
#Around("call(* Ent.getSth())")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
logger.info("Inside around + 12:52");
Ent ent = (Ent) pjp.getTarget();
logger.info("Number: " + ent.getImportantNumber());
return pjp.proceed();
}
}
some class
public class AspectApp {
Logger logger = LoggerFactory.getLogger(AspectApp.class);
#GetMapping("/")
public String main() {
logger.info("Method main started + 11:01");
A a = new A();
a.shouldDoSthAndCallMethodGetSth(1);
}
}
A
public class A {
Logger logger = LoggerFactory.getLogger(A.class);
public void shouldDoSthAndCallMethodGetSth(Integer a) {
// ...
Ent ent = new Ent();
ent.setImportantNumber(1);
logger.info("Method A do sth and ...");
ent.getSth();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Testing</name>
<description>App for tests</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>11</complianceLevel>
<source>11</source>
<target>11</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

I can't tell where the problem is. normally you don't need to keep to maven clean install everytime you change something in your code.I suggest you use devtools maybe

Related

Spring Boot: Could not resolve matching constructor when using scope: prototype

Problem
I'm having an issue where, any bean I define with the scope = prototype causes a BeanCreationException:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myClass' defined in class path resource [application-context.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:218)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1166)
at com.example.coaching.BeanScopeDemoAppKt.main(BeanScopeDemoApp.kt:10)
at com.example.coaching.BeanScopeDemoAppKt.main(BeanScopeDemoApp.kt)
Example
This is the most basic example I could create that reproduced the problem...
MyClass.java:
Variation 1
public class MyClass {
public String doNothing() {
return "Do nothing";
}
}
Variation 2
public class MyClass {
public MyClass() {}
public String doNothing() {
return "Do nothing";
}
}
application-context.xml
<bean id="myClass"
class="com.example.coaching.models.MyClass"
scope="prototype">
</bean>
MyApp.kt
class MyApp
fun main() {
val context = ClassPathXmlApplicationContext("beanScope-applicationContext.xml")
val myClass = context.getBean("myClass", MyClass::class) as MyClass
println(myClass.doNothing())
}
Other Info
I experienced this in a more complex project, but made this one to try to narrow down the problem and expected I would find something, but I have no clue.
If I change the scope to singleton, it works fine.
Happens with xml configuration as well as annotations
Tried creating MyClass in both Kotlin and Java
Here's my pom.xml just in case
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring Demo Annotations</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<kotlin.version>1.4.31</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

Repository bean cannot be found (No idea why)

I'm trying to run my application and I'm receiving this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.danielturato.product.services.ProductServiceImpl required
a bean of type 'com.danielturato.product.persistence.ProductRepository' that could not be
found.
Action:
Consider defining a bean of type 'com.danielturato.product.persistence.ProductRepository' in
your configuration.
I have no idea why this is occurring. I've tried to look at past solutions where its said to use the #EnableMongoRepository to point to the correct package however I have tried this and it doesn't work. I've also tried adding the #Repository annotation above my repository (even though its not needed) and it doesn't work still. Here is my code for my repository, application & where the repository is failing to be injected.
Application:
#SpringBootApplication
#ComponentScan("com.danielturato")
public class ProductServiceApplication {
private static final Logger LOG = LoggerFactory.getLogger(ProductServiceApplication.class);
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
Repository:
public interface ProductRepository extends ReactiveCrudRepository<ProductEntity, String> {
Mono<ProductEntity> findByProductId(int productId);
}
ProductServiceImpl:
#RestController
public class ProductServiceImpl implements ProductService {
private static final Logger LOG = LoggerFactory.getLogger(ProductServiceImpl.class);
private final ServiceUtil serviceUtil;
private final ProductRepository repository;
private final ProductMapper mapper;
#Autowired
public ProductServiceImpl(ProductRepository repository, ProductMapper mapper, ServiceUtil serviceUtil) {
this.repository = repository;
this.mapper = mapper;
this.serviceUtil = serviceUtil;
}
Pom file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.danielturato</groupId>
<artifactId>product-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>product-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</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>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.danielturato</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.danielturato</groupId>
<artifactId>util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.0.Beta2</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
If anyone can suggest for me anything to try or would like me to put more info here please let me know.
The stack trace you have included in your question does point to the ProductRepository not being available for autowiring and as a previous comment has pointed out this is because you are missing the #Repository annotation from your repository.
Another reason is if your repository cannot find a matching entity. This might be for example if the Id is the wrong type or is missing the #Id annotation, if the entity doesn't have either #Entity/#Document or if it is missing an all args constructor. Plus in your case you have added a findByProductId() method so your entity will need a productId field too.
I would also remove the #ComponentScan annoatation from your application class as this is included by default in #SpringBootApplication unless you are intentionally pointing it at a different class path.
If this still fails as you have mentioned in your comments is it failing for the same reason or is there a different error now related to ProductMapper or ServiceUtil?

CAS Maven Overlay And Spring Boot do not work together

I create a spring boot application from spring.io, then add CAS dependecy to pom file of project as below.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp</artifactId>
<version>${cas.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>
after that start spring boot application, but CAS does not start in spring boot application.
what is the main problem in this usage of CAS?
Is the method of using the CAS at this way wrong?
_____________________________________________________________
finaly I solve my problem. I change the pom file as below
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<javaparser-core.version>3.12.0</javaparser-core.version>
<start.class>org.apereo.cas.web.CasWebApplication</start.class>
<start.class2>x.y.sso.SingleSignOnApplication</start.class2>
<h2.version>1.4.197</h2.version>
<cas.version>6.0.1</cas.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp-tomcat</artifactId>
<version>${cas.version}</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${javaparser-core.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration</artifactId>
<version>${cas.version}</version>
</dependency>
</dependencies>
<build>
<finalName>cas</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start.class2}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!--<recompressZippedFiles>false</recompressZippedFiles>-->
<archive>
<compress>false</compress>
<manifestFile>
${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp-tomcat/META-INF/MANIFEST.MF
</manifestFile>
</archive>
<overlays>
<overlay>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp-tomcat</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
then I create a Application class
#EnableDiscoveryClient
#SpringBootApplication(exclude = {
HibernateJpaAutoConfiguration.class,
JerseyAutoConfiguration.class,
JmxAutoConfiguration.class,
DataSourceAutoConfiguration.class,
DataSourceHealthIndicatorAutoConfiguration.class,
RedisAutoConfiguration.class,
MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class,
CassandraAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class})
#EnableConfigurationProperties({CasConfigurationProperties.class})
#EnableAsync
#EnableTransactionManagement(proxyTargetClass = true)
#EnableScheduling
public class SingleSignOnApplication {
public static void main(String[] args) {
SpringApplication.run(SingleSignOnApplication.class, args);
}
}
by this configuration, build maven goal and execution project by spring boot work correctly.
CAS is already a spring boot web application. Therefor have a look into cas-server-webapp-init-6.0.1.jar and look CasWebApplication.java.
#EnableDiscoveryClient
#SpringBootApplication(exclude={HibernateJpaAutoConfiguration.class, JerseyAutoConfiguration.class, GroovyTemplateAutoConfiguration.class, JmxAutoConfiguration.class, DataSourceAutoConfiguration.class, DataSourceHealthIndicatorAutoConfiguration.class, RedisAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, CassandraAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class})
#EnableConfigurationProperties({CasConfigurationProperties.class})
#EnableAsync
#EnableTransactionManagement(proxyTargetClass=true)
#EnableScheduling
public class CasWebApplication
{
public static void main(String[] args)
{
Map<String, Object> properties = CasEmbeddedContainerUtils.getRuntimeProperties(Boolean.TRUE);
Banner banner = CasEmbeddedContainerUtils.getCasBannerInstance();
new SpringApplicationBuilder(new Class[] { CasWebApplication.class })
.banner(banner)
.web(WebApplicationType.SERVLET)
.properties(properties)
.logStartupInfo(true)
.contextClass(CasWebApplicationContext.class)
.run(args);
}
}
Remove the spring-boot-starter dependencies and CAS should start itself as a web application.
For further investigation I would recommend you to download the war from https://search.maven.org/artifact/org.apereo.cas/cas-server-webapp/6.0.1/war and inspect it with a tool like jd-gui.

SpringBoot: Defining the main class in pom.xml file

I've generated a Spring Boot web application using Spring Initializer, embedded Tomcat, Thymeleaf template engine.Technologies used: Spring Boot 1.4.2.RELEASE, Spring 4.3.4.RELEASE, Thymeleaf 2.1.5.RELEASE, Tomcat Embed 8.5.6, Maven 3, Java 8.
I have this pom.xml file,
and I generate the war using this command
mvn clean package -DskipTests -Dspring.profiles.active=pebloc,war -DAPPKEY=pebloc
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bookcloud</groupId>
<artifactId>bookcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>bookcloud</name>
<description>Book Cloud </description>
<profiles>
<profile>
<id>jar</id>
<properties>
<spring.boot.mainclass>com.bookcloud.iot.BookCloudApplication</spring.boot.mainclass>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<spring.boot.mainclass>com.bookcloud.iot.BookCloudApplicationWar</spring.boot.mainclass>
</properties>
</profile>
</profiles>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>spring-boot-email-core</artifactId>
<version>0.5.1</version>
</dependency>
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>spring-boot-thymeleaf-email</artifactId>
<version>0.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.icegreen/greenmail -->
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>1.5.3</version>
<optional>true</optional>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- hot swapping, disable cache for template, enable live reload -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>${spring.boot.mainclass}</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
but I still got this error:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.2.RELEASE:repackage (default) on project bookcloud: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.2.RELEASE:repackage failed: Unable to find a single main class from the following candidates [com.bookcloud.iot.BookCloudApplication, com.bookcloud.iot.BookCloudApplicationWar] -> [Help 1]
BookCloudApplication.java
#Profile("!war")
#SpringBootApplication
#Import({SecurityConfig.class ,PersistenceConfig.class, ServiceConfig.class})
public class BookCloudApplication {
public static void main(String[] args) {
SpringApplication.run(BookCloudApplication.class, args);
}
}
BookCloudApplicationWar.java
#Profile("war")
#Import({SecurityConfig.class ,PersistenceConfig.class})
#SpringBootApplication
public class BookCloudApplicationWar extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BookCloudApplicationWar.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(BookCloudApplicationWar.class, args);
}
}
Maven profiles has no relation to Spring profiles.
You have two Maven profiles: jar, war
You either use:
mvn clean package -Pjar
or
mvn clean package -Pwar
The error you are getting is while building the artifact because pom needs:
<start-class>your.app.entry.point.Main</start-class>
inside the properties element.
I would suggest to have only one start class regardless of the Maven profile.
something like:
pom.xml:
...
<modelVersion>4.0.0</modelVersion>
<groupId>com.asimio.cloud</groupId>
<artifactId>zuul-server</artifactId>
<version>0-SNAPSHOT</version>
<packaging>${packaging.type}</packaging>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<start-class>your.app.entry.point.Main</start-class>
<packaging.type>jar</packaging.type>
...
<profiles>
<profile>
<id>war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
...
</profile>
</profiles>
...
Main.java:
package your.app.entry.point;
...
#SpringBootApplication
#Import({SecurityConfig.class ,PersistenceConfig.class, ServiceConfig.class})
public class App extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(App.class);
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
No need for Spring profiles. This artifact can now be built using either Maven profile and will run either using:
java -jar .....
when building this artifact as a jar
or
as a war file deployed to a servlet container when built using the -Pwar Maven profile.
Maven profiles and Spring profiles are two different concepts.
You should also run Maven using the war profile, in order for the spring.boot.mainclass property to be set with the correct matching value.
Add -Pwar to the command line in order to activate the war Maven profile.
mvn clean package -DskipTests -Pwar -Dspring.profiles.active=pebloc,war -DAPPKEY=pebloc

PaxExam OSGI Container and ServiceLookupException

I have built a very simple bundle which has zero dependencies and imports no packages. Its only content is a CalculatorService interface and corresponding implementation class containing just a simple add(int a, int b) method.
I have created two PaxExam test containers for this bundle, one using a Karaf container, and the other an OSGI container. The Karaf container tests work fine, but the OSGI test container does not.
To clarify a bit... if I remove the injection of the CalculatorService into the OSGI test container, and directly instantiate the CalculatorServiceImpl class in my JUnit test case, it works fine. So the class from my simple bundle is visible to the OSGI test container.
Some questions:
Is there something I am missing in my pom.xml files to make this work?
Should I add more bundles to my OsgiTestClient.config() method?
Other ideas on what is keeping is very stripped down example from working?
The following is the stack trace I get when trying to inject the CalculatorService into my PaxExam OSGI test container.
org.ops4j.pax.swissbox.tracker.ServiceLookupException: gave up waiting for service info.xyz.common.Calculator
at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:199)
at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:136)
at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectField(ServiceInjector.java:89)
at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectDeclaredFields(ServiceInjector.java:69)
at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectFields(ServiceInjector.java:61)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.createTest(ContainerTestRunner.java:61)
at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:68)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:37)
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.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:124)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:97)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:73)
at org.ops4j.pax.exam.nat.internal.NativeTestContainer.call(NativeTestContainer.java:112)
at org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactor.invoke(AllConfinedStagedReactor.java:84)
at org.ops4j.pax.exam.junit.impl.ProbeRunner$2.evaluate(ProbeRunner.java:267)
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.ops4j.pax.exam.junit.impl.ProbeRunner.run(ProbeRunner.java:98)
at org.ops4j.pax.exam.junit.PaxExam.run(PaxExam.java:93)
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)
The pom.xml for my simple bundle containing the Calculator service is as follows:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>info.xyz</groupId>
<artifactId>xyz-businessLogic</artifactId>
<version>0.0.1</version>
<packaging>bundle</packaging>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Import-Package>
</Import-Package>
<Export-Package>
info.xyz.common,
info.xyz.common.impl
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
It is clear there are zero dependencies to my simple bundle, and the packages containing the Calculator and CalculatorImpl files are exported. Below is the blueprint.xml file for defining these services.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance
http://aries.apache.org/xmlns/jpa/v1.0.0 http://aries.apache.org/xmlns/jpa/v1.0.0
http://aries.apache.org/xmlns/transactions/v1.0.0 http://aries.apache.org/xmlns/transactions/v1.0.0">
<bean id="calculatorService" class="info.xyz.common.impl.CalculatorImpl" />
<service ref="calculatorService" interface="info.xyz.common.Calculator" />
</blueprint>
Next, the pom.xml for my PaxExam OSGI container is as follows:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>info.xyz</groupId>
<artifactId>xyz-test-osgi</artifactId>
<version>0.0.1</version>
<parent>
<groupId>info.xyz</groupId>
<artifactId>xyz</artifactId>
<version>0.0.1</version>
<relativePath>../xyz</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>${pax.exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>${pax.exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-mvn</artifactId>
<version>${pax.exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
<version>${pax.url.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<version>${pax.exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-inject</artifactId>
<version>${pax.exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${ch.qos.logback.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${ch.qos.logback.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>${javax.inject.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Testing target -->
<dependency>
<groupId>info.xyz</groupId>
<artifactId>xyz-businessLogic</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Needed if you use versionAsInProject() -->
<plugin>
<groupId>org.apache.servicemix.tooling</groupId>
<artifactId>depends-maven-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>generate-depends-file</id>
<goals>
<goal>generate-depends-file</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Finally, the OSGI Test class is given as follows:
package info.xyz.test.osgi;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import info.xyz.common.Calculator;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.Constants;
#RunWith(PaxExam.class)
#ExamReactorStrategy(PerMethod.class)
public class OsgiTestClient
{
#Inject
protected Calculator _calculator;
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe)
{
System.out.println("TestProbeBuilder gets called");
probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*");
probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common");
probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common.impl");
return probe;
}
#Configuration
public Option[] config()
{
return new Option[] {
junitBundles(),
mavenBundle().groupId("info.xyz").artifactId("xyz-businessLogic").versionAsInProject(),
};
}
#Test
public void testAdd()
{
info.xyz.common.impl.CalculatorImpl calculator = new info.xyz.common.impl.CalculatorImpl();
int result = calculator.add(1, 2);
System.out.println("--- testing: ");
}
}
One final comment, if I comment out the code for injecting the CalculatorService, the code runs fine (as I am manually instantiating the CalculatorImpl class). So my test container does have both compile-time and run-time visibility to the Calculator interface and implementation. But injection of this service is not working.
And a final reminder, when I build a PaxExam Karaf Test Container, the injection of the Calculator service is successful and the test cases run fine. The error is when running the PaxExam OSGI container described in this post.
Yes, then it is that the blueprint stack/libraries are not installed by default in native container (but they are in Karaf).
You need to add this deps to your test pom:
<dependency>
<groupId>org.apache.aries</groupId>
<artifactId>org.apache.aries.util</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.aries.proxy</groupId>
<artifactId>org.apache.aries.proxy.api</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.aries.proxy</groupId>
<artifactId>org.apache.aries.proxy.impl</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.api</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.core.compatibility</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.cm</artifactId>
<version>1.0.5</version>
</dependency>
And add the following bundles to your configuration in your test:
mavenBundle().groupId("org.apache.aries").artifactId("org.apache.aries.util").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.api").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.impl").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.api").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.cm").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core").versionAsInProject(),
mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core.compatibility").versionAsInProject().noStart(),
That should make the trick!

Resources