#Async annotation does not works when war is deployed on JBoss - spring

I have an application that contains an API Rest implemented as a Spring Boot application (1.5.18.RELEASE version)
This API contains a controller that executes a service method asynchronous. The method is marked with #Async annotation
The #EnableAsync annotation is set on my configuration class.
When i execute the application like a typical Spring Boot application, the method is executed asynchronous. if i generate a war (using maven) and this war is deployed on JBoss (6.4 Version), the same service is executed synchronous.
Could someone explain me this behavior? Should i add any type of configuration?
The source code is below:
The Spring Boot configuration
#SpringBootApplication
#EnableCustomConfiguration
#EnableCaching
#EnableScheduling
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
My custom annotation:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Import({CustomServicesConfiguration.class})
#Documented
public #interface EnableCustomConfiguration {
}
My configuration class:
#Configuration
#ComponentScan("com.bs.custom.api")
#EntityScan(basePackages = "com.bs.custom.api.domain", basePackageClasses = Jsr310JpaConverters.class)
#EnableJpaRepositories(basePackages = "com.bs.custom.api.repository")
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
#EnableAsync
public class CustomServicesConfiguration {
static {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}

I've modified my WebApplication class to extends from SpringBootServletInitializer, as is defined on Spring Boot reference guide (thanks M.Deinum)
The final WebApplication class source code is below:
#SpringBootApplication
#EnableCustomConfiguration
#EnableCaching
#EnableScheduling
#EnableAsync
public class WebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
}
Now, asynchronous methods run correctly on JBoss

Related

Spring boot - scan packages

I am starting to write an application in spring boot and below is how my package structure looks:
com.practice.spring.project.helloworld.HelloworldApplication.java
com.practice.spring.project.repository.EmployeeRepository.java
com.practice.spring.project.model.Employee.java
Below is how i had my application startup successfully,
#SpringBootApplication
#ComponentScan(basePackages = "com.practice.spring.project.DB", basePackageClasses = InitDatabase.class)
#EnableJpaRepositories(basePackages = "com.practice.spring.project.repository" , basePackageClasses = EmployeeRepository.class)
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
#Bean
public CommandLineRunner run(EmployeeRepository employeeRepository) throws Exception {
return (args) -> {
System.out.println("Calling it after the application context is all loaded up");
employeeRepository.save(new Employee("Ashwin", "Architect"));
};
}
}
My question is should I have to specify the base-packages & baseClasses for every class I add ? It would be tough if have 10 packages having 10 different classes.
Am sure there should be an easier way to scan and instantiate classes in different package.
Figured out a way - set the basePackages to com.practice.spring.project.*
#ComponentScan(basePackages = "com.practice.spring.project.*")

Replace Beans.xml configuration in Spring

How can I replace beans.xml file for testing purposes?
I use
#SpringBootApplication
#ImportResource("classpath:Beans.xml")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
to init class, but in my testing class
#RunWith(SpringRunner.class)
#SpringBootTest
public class ArrayCointainerTest {
I'd like to use another one.
Any idea for this?
Define a separate configuration class which has you beans xml imported and annotate that with #TestConfiguration. Spring boot automatically pick this up as your test configuration
Detecting test configuration

Execute CommandLineRunner outside #SpringBootApplication

This is based on https://spring.io/guides/gs/accessing-data-jpa/
I tried to move demo() in a different class in a different package (Application still on top of the filesystem hierarchy)
How do I make demo() run when i boot the project?
Application.java
package com.company.app
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
CommandLineRunner.java
package com.company.app.runner
public class Test {
#Bean
public CommandLineRunner demo() {
System.out.print("Run 1");
return (args) -> {
System.out.print("Run 2");
};
}
}
Add #Configuration to the Test class so that it is picked up when the classpath is scanned.
I haven't seen a Lambda for the CommandLineRunner before. Very nifty and saves having to create a class that specifically implements the CommandLineRunner.
Otherwise, you could implement CommandLineRunner to test and annotate as #Component.
#Component
public class ApplicationLoader implements CommandLineRunner {
#Override
public void run(String... strings) throws Exception {
System.out.print("Run 2");
}
}
* Update *
Answering the question in the comment with this update as I have more room to type...
#SpringBootApplication composes those other annotations as you indicated but those annotations are only applied to the specific class that it is defined on. The #Configuration annotation is telling Spring that the class defines beans that should be managed by the application context. The #ComponentScan tells spring to look through the classpath for classes that have specific annotations (e.g. #Component, #Service, #Configuration) and then act on those classes based on the type of annotation. the #EnableAutoConfiguration is the magic that loads appropriate beans based on the project dependencies (e.g. if mongo driver is on the classpath then create a MongoTemplate).

getting #autowired intance null when try trying to do operation on it,throwing null pointer exception

I am trying to save data on gemfire using crud repository. I have created one operation class to call save method of repository but at autowired instance I am getting null pointer exception. Below is my code:
public interface GeodeRepository extends CrudRepository<KeyValueBean, String> {
#Override
public KeyValueBean findOne(String name);
#Override
public <S extends KeyValueBean> Iterable<S> save(Iterable<S> entities);
}
#EnableGemfireRepositories(basePackageClasses = GeodeRepository.class)
#EnableAutoConfiguration
#Configuration
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean)); // <--- i am getting
// repository as null so
// getting null pointer
// exception
}
}
When we #Autowired any class make sure, you have declared that class as a #Component.
for example:
#Component
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean));
}
}
and try using #Autowired to Operation class to your class
in which class your are calling your saveKeyValueData() method.
So, what is not apparent from your example is how you "bootstrap" your application and it's features (e.g. Repositories) into action.
It is not simply enough to add the Spring #Configuration, Spring Boot's #EnableAutoConfiguration and SD GemFire's #EnableGemfireRepositories annotations and expect everything to be auto-configured and wired up successfully. I.e. you need a bootstrapping mechanism, like Spring Boot, especially if you are using the #EnableAutoConfiguration annotation.
For example...
import org.springframework.boot.SpringApplication;
...
class MyApplication {
public static void main(String[] args) {
SpringApplication.run(Operations.class, args);
}
}
Now, you could remove the #EnableAutoConfiguration from your Operations class and add the #SpringBootApplication to the MyApplication class, like so...
#SpringBootApplication
class MyApplication {
...
}
#SpringBootAppliation combines together Spring's #Configuration with Spring Boot's #EnableAutoConfiguration, along with many other useful meta-annotations, like Spring's #ComponentScan, enabling all sorts of magic to happen.
But, if you are not using Spring Boot, you can always bootstrap you application with the AnnotationConfigApplicationContext, like so..
class MyApplication
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(Operations.class);
applicationContext.registerShutdownHook();
}
}
This is essentially what the Spring Boot, SpringApplication class does for you anyway.
If you are developing a Web application, then of course you can specify the type of ApplicationContext created since you are using Java config, for instance. See here for more details.
Hope this helps!
Cheers,
John

Can #Configuration work without #componentScan (Spring JavaConfig #annotaion)

--Appconfig.java
#Configuration
public class AppConfig {
#Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
--interface.java
public interface HelloWorld {
void printHelloWorld(String msg);
}
--ipml.java
public class HelloWorldImpl implements HelloWorld {
public void printHelloWorld(String msg) {
System.out.println("Hello! : " + msg);
--
}
--App.java
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new
new AnnotationConfigApplicationContext(AppConfig.class);
HelloWorld obj = (HelloWorld) context.getBean(HelloWorldImpl.class);
obj.printHelloWorld("Spring3 Java Config");
}
}
My program can works, but my question is why I don't need to add #componentScan in Appconfig.java .
It seems to #Configuration and #Bean can be found by Spring whithout using #componentScan.
I thought if you want to use #annotation ,you must use #componentScan or
context:component-scan(xml),
am I right?
#ComponentScan allows spring to auto scan all your components with #Component annotated. Spring uses the base-package attribute, which indicates where to find components.
#Configuration is meta annotated with #Component, which marks it eligible for classpath scanning.
#Configuration (AppConfig class) is registered when you use
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
#Bean doesn't need #ComponentScan as all these beans are created explicitly when spring encounters this annotation.

Resources