Lets say I've got a JavaFx class and an ViewState class which needs to have referance of stage created in start method. How am I able to autowire such dependency? I know that Stage.class is not annotated as #Component so Spring is unable to detect duch #Bean.
#SpringBootApplication
#ComponentScan({"controller","service","dao","javafx.stage.Stage"})
#EntityScan( basePackages = {"Model"})
#Import({ SpringConfig.class})
public class JavaFXandSpringBootTestApplication extends Application{
private ApplicationContext ctx;
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage stage) throws Exception {
ViewState viewState = ctx.getBean(ViewState.class);
}
ViewState class:
#Componenet
public class ViewState {
#Autowired
private ApplicationContext ctx;
private Stage stage;
#Autowired
public ViewState(Stage stage)
{
this.stage = stage;
}
}
Compiler massage:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javafx.stage.Stage' available: expected at least 1
You probably don't want to do this at all: your ViewState class would seem to be a model class of some kind, so it should not have references to UI elements (such as Stages).
For completeness, though, here is an example that works, using ConfigurableApplicationContext.getBeanFactory().registerResolvableDependency(...). Note that, since you won't be able to create the View object until the stage is registered, you need to make the View bean #Lazy:
package example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
#Component
#Lazy
public class View {
#Autowired
public View(Stage stage) {
Button close = new Button("Close");
close.setOnAction(e -> stage.hide());
StackPane root = new StackPane(close);
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
}
package example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import javafx.application.Application;
import javafx.stage.Stage;
#SpringBootApplication
public class Main extends Application {
private ConfigurableApplicationContext ctx ;
#Override
public void start(Stage primaryStage) {
ctx = SpringApplication.run(Main.class);
ctx.getBeanFactory().registerResolvableDependency(Stage.class, primaryStage);
ctx.getBean(View.class);
}
#Override
public void stop() {
ctx.close();
}
public static void main(String[] args) {
launch(args);
}
}
Related
I've spring-data-aerospike project at github in branch npe.
The application.properties is
aerospike.host=localhost
aerospike.port=3000
aerospike.namespace=test
aerospike.timeout=125
os.name=Linux
line.separator=\n
The spring ApplicationContext is
mport com.aerospike.demo.simplespringbootaerospikedemo.repositories.AerospikeUserRepository;
import com.aerospike.client.Host;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.aerospike.config.AbstractAerospikeDataConfiguration;
import org.springframework.data.aerospike.repository.config.EnableAerospikeRepositories;
import java.util.Collection;
import java.util.Collections;
#Configuration
#EnableConfigurationProperties(AerospikeConfigurationProperties.class)
#EnableAerospikeRepositories(basePackageClasses = AerospikeUserRepository.class)
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
#Autowired
private AerospikeConfigurationProperties aerospikeConfigurationProperties;
#Override
protected Collection<Host> getHosts() {
return Collections.singleton(new Host(aerospikeConfigurationProperties.getHost(), aerospikeConfigurationProperties.getPort()));
}
#Override
protected String nameSpace() {
return aerospikeConfigurationProperties.getNamespace();
}
}
The main application is -
import com.aerospike.demo.simplespringbootaerospikedemo.configuration.AerospikeConfiguration;
import com.aerospike.demo.simplespringbootaerospikedemo.objects.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.aerospike.core.AerospikeTemplate;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.stream.Stream;
import org.joda.time.DateTime;
public class TestSpringConfig {
public static void main(String[] args) throws IOException {
System.out.println(ClassLoader.getSystemResourceAsStream("application.properties").available());
Properties props = new Properties();
InputStream resourceAsStream = ClassLoader.getSystemResourceAsStream("application.properties");
if (resourceAsStream != null) {
props.load(resourceAsStream);
}
if(props != null) {
System.setProperties(props);
}
try {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AerospikeConfiguration.class);
AerospikeTemplate template = ctx.getBean(AerospikeTemplate.class);
template.save(new User(123, "","", 12, DateTime.now().plusSeconds(60).getMillis()));
} catch (Exception e) {
StackTraceElement[] st = e.getStackTrace();
Stream.of(st).forEach(System.out::println);
} catch (ExceptionInInitializerError e) {
System.out.println(e.getCause());
e.getCause().printStackTrace();
}
}
}
when I run the main application I get below error -
java.lang.NullPointerException
at java.base/sun.nio.fs.UnixPath.normalizeAndCheck(UnixPath.java:75)
at java.base/sun.nio.fs.UnixPath.(UnixPath.java:69)
at java.base/sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:279)
at java.base/java.io.FilePermission.(FilePermission.java:207)
at java.base/sun.security.provider.PolicyFile.getKnownPermission(PolicyFile.java:886)
at java.base/sun.security.provider.PolicyFile.getInstance(PolicyFile.java:836)
at java.base/sun.security.provider.PolicyFile.addGrantEntry(PolicyFile.java:735)
at java.base/sun.security.provider.PolicyFile.initDefaultPolicy(PolicyFile.java:491)
at java.base/sun.security.provider.PolicyFile$2.run(PolicyFile.java:338)
at java.base/sun.security.provider.PolicyFile$2.run(PolicyFile.java:335)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:335)
at java.base/sun.security.provider.PolicyFile.init(PolicyFile.java:328)
at java.base/sun.security.provider.PolicyFile.(PolicyFile.java:281)
at java.base/java.security.Policy.loadPolicyProvider(Policy.java:207)
at java.base/java.security.Policy.getPolicyNoCheck(Policy.java:178)
at java.base/java.security.ProtectionDomain.implies(ProtectionDomain.java:321)
at java.base/java.security.ProtectionDomain.impliesWithAltFilePerm(ProtectionDomain.java:353)
at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:450)
at java.base/java.security.AccessController.checkPermission(AccessController.java:897)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:48)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:45)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at ch.qos.logback.core.util.Loader.(Loader.java:45)
at ch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(ContextInitializer.java:109)
at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:138)
at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at org.slf4j.impl.StaticLoggerBinder.(StaticLoggerBinder.java:55)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:417)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:362)
at org.apache.commons.logging.LogAdapter$Slf4jAdapter.createLocationAwareLog(LogAdapter.java:130)
at org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:91)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59)
at org.springframework.context.support.AbstractApplicationContext.(AbstractApplicationContext.java:178)
at org.springframework.context.support.GenericApplicationContext.(GenericApplicationContext.java:112)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.(AnnotationConfigApplicationContext.java:67)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.(AnnotationConfigApplicationContext.java:91)
at com.aerospike.demo.simplespringbootaerospikedemo.TestSpringConfig.main(TestSpringConfig.java:27)
Any idea how to fix this error?
The workaround that you tried to implement in order to "Autowire" AerospikeTemplate bean doesn't work and results in a NPE. There are a few ways to "Autowire" a bean (in this case an AerospikeTemplate bean) in the static main() method, here is a StackOverFlow question that talks about this scenario:
How to use autowired (#Autowired) references from main(String[] args) method?
But the main question is what are you trying to achieve? the conventional way of using Spring Data Aerospike Repository/Template is to Autowire the repository/template in a service (also a bean) and then call the service methods from something like a controller/test/different service etc... Most Spring applications doesn't include logic inside the static main() method - it can be done but it doesn't make much sense.
To autowire AerospikeTemplate you need to setup Spring Boot application in the main method (check an example here):
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
then you can autowire AerospikeTemplate anywhere you need.
If you are developing a console application using Spring Boot I would suggest using org.springframework.boot.CommandLineRunner. For example:
#Component
public class CommandLineRunnerImpl implements CommandLineRunner {
#Autowired
AerospikeTemplate template;
#Override
public void run(String... args) throws Exception {
template.save(new User(123, "","", 12, DateTime.now().plusSeconds(60).getMillis()));
}
}
I want to do a self-cleaning test
In my situation, I have one of the components depend on a directory
public class FileRepositoryManagerImpl implements ....
#Value("${acme.fileRepository.basePath}")
private File basePath;
}
The value is defined in the application.yml file, and in DEV it points to a directory under build.
This is not the worst idea, because gradle clean will eventually clean up the mess the tests create.
But, really, what I would like to achieve here, is to make sure that every test runs in an isolated temporary directory that is cleaned up after execution.
I know that JUnit has a tool for the temporary directories. But once I have defined that directory in the scope of JUnit 4, how do I tell Spring to use that temporary directory?
I tried the inner class unsuccessfully:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { SecurityBeanOverrideConfiguration.class, App.class })
#EnableConfigurationProperties
public abstract class AbstractFileRepositoryManagerIntTests {
private final static TemporaryFolder temporaryFolder = new TemporaryFolder();
#ClassRule
public static TemporaryFolder getTemporaryFolder()
{
return temporaryFolder;
}
#ConfigurationProperties(prefix = "acme")
static class Configuration
{
public FileRepository getFileRepository()
{
return new FileRepository();
}
static class FileRepository
{
public File basePath() throws Exception
{
return temporaryFolder.newFolder("fileRepositoryBaseDir");
}
}
}
}
I was thinking about tinkering with the Environment, but what should be the correct way to inject properties programmatically in a Spring Boot test?
I can think of at least four different approaches to your problem. All with their own advantages and disadvantages.
Approach 1: ReflectionTestUtils
You are using #Value annotation on a private instance property (please, don't to that anymore!). Hence, you can not change acme.fileRepository.basePath on the fly without reflection.
package demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryApp.class, args);
}
#Component
public class FileRepository {
#Value("${acme.fileRepository.basePath}")
private File basePath;
public File getBasePath() {
return basePath;
}
}
}
Changing basePath after each test with ReflectionTestUtils.setField. Because we are using Spring's TestExecutionListener, that gets initialized before Junit rules are initialized, we are forced to manage the temporary folder in beforeTestExecution and afterTestMethod.
package demo;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryApp.class)
#TestExecutionListeners(listeners = FileRepositoryAppTest.SetBasePath.class, mergeMode = MERGE_WITH_DEFAULTS)
public class FileRepositoryAppTest {
private static TemporaryFolder temporaryFolder = new TemporaryFolder();
#Autowired
private FileRepositoryApp.FileRepository fileRepository;
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(fileRepository.getBasePath());
assertEquals(temporaryFolder.getRoot(), fileRepository.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(fileRepository.getBasePath());
assertEquals(temporaryFolder.getRoot(), fileRepository.getBasePath());
}
static class SetBasePath implements TestExecutionListener {
#Override
public void beforeTestExecution(TestContext testContext) throws IOException {
temporaryFolder.create();
if (testContext.hasApplicationContext()) {
FileRepositoryApp.FileRepository bean = testContext.getApplicationContext().getBean(FileRepositoryApp.FileRepository.class);
ReflectionTestUtils.setField(bean, "basePath", temporaryFolder.getRoot());
}
}
#Override
public void afterTestMethod(TestContext testContext) {
temporaryFolder.delete();
}
}
}
Approach 2: Configuration properties
Introduce a configuration properties class for your application configuration. It gives you type safety for free and we don't rely on reflection anymore.
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryWithPropertiesApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryWithPropertiesApp.class, args);
}
#Component
public class FileRepository {
private final FileRepositoryProperties fileRepositoryProperties;
public FileRepository(FileRepositoryProperties fileRepositoryProperties) {
this.fileRepositoryProperties = fileRepositoryProperties;
}
public File getBasePath() {
return fileRepositoryProperties.getBasePath();
}
}
#Component
#ConfigurationProperties(prefix = "acme.file-repository")
public class FileRepositoryProperties {
private File basePath;
public File getBasePath() {
return basePath;
}
public void setBasePath(File basePath) {
this.basePath = basePath;
}
}
}
Because we are using Spring's TestExecutionListener, that gets initialized before Junit rules are initialized, we are forced to manage the temporary folder in beforeTestExecution and afterTestMethod.
package demo;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryWithPropertiesApp.class)
#TestExecutionListeners(listeners = FileRepositoryWithPropertiesTest.SetBasePath.class, mergeMode = MERGE_WITH_DEFAULTS)
public class FileRepositoryWithPropertiesTest {
private static TemporaryFolder temporaryFolder = new TemporaryFolder();
#Autowired
private FileRepositoryWithPropertiesApp.FileRepository bean;
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
static class SetBasePath implements TestExecutionListener {
#Override
public void beforeTestExecution(TestContext testContext) throws IOException {
temporaryFolder.create();
if (testContext.hasApplicationContext()) {
FileRepositoryWithPropertiesApp.FileRepositoryProperties bean = testContext.getApplicationContext().getBean(FileRepositoryWithPropertiesApp.FileRepositoryProperties.class);
bean.setBasePath(temporaryFolder.getRoot());
}
}
#Override
public void afterTestMethod(TestContext testContext) {
temporaryFolder.delete();
}
}
}
Approach 3: Refactor your code (my favorite)
Extract basePath into its own class and hide it behind an api. Now you don't need to poke with your application properties and a temporary folder anymore.
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryWithAbstractionApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryWithAbstractionApp.class, args);
}
#Component
public class FileRepository {
private final FileRepositorySource fileRepositorySource;
public FileRepository(FileRepositorySource fileRepositorySource) {
this.fileRepositorySource = fileRepositorySource;
}
public File getBasePath() {
return fileRepositorySource.getBasePath();
}
}
#Component
public class FileRepositorySource {
private final FileRepositoryProperties fileRepositoryProperties;
public FileRepositorySource(FileRepositoryProperties fileRepositoryProperties) {
this.fileRepositoryProperties = fileRepositoryProperties;
}
// TODO for the sake of brevity no real api here
public File getBasePath() {
return fileRepositoryProperties.getBasePath();
}
}
#Component
#ConfigurationProperties(prefix = "acme.file-repository")
public class FileRepositoryProperties {
private File basePath;
public File getBasePath() {
return basePath;
}
public void setBasePath(File basePath) {
this.basePath = basePath;
}
}
}
We don't need any additional testing facility anymore and we can use #Rule on TemporaryFolder instead.
package demo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.when;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryWithAbstractionApp.class)
public class FileRepositoryWithAbstractionTest {
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#MockBean
private FileRepositoryWithAbstractionApp.FileRepositorySource fileRepositorySource;
#Autowired
private FileRepositoryWithAbstractionApp.FileRepository bean;
#Before
public void setUp() {
when(fileRepositorySource.getBasePath()).thenReturn(temporaryFolder.getRoot());
}
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
}
Approach 4: TestPropertySource
Use Spring's TestPropertySource annotation to override properties in a test selectively. Because a Java anntotation can not have a dynamic value, you need to decide beforehand where you want to create your directory and keep in mind your test is bound to a specific operating system due to the used os path separator.
package demo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static demo.FileRepositoryTestPropertySourceTest.BASE_PATH;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryApp.class)
#TestPropertySource(properties = "acme.fileRepository.basePath=" + BASE_PATH)
public class FileRepositoryTestPropertySourceTest {
static final String BASE_PATH = "/tmp/junit-base-path";
private Path basePath = Paths.get(BASE_PATH);;
#Autowired
private FileRepositoryApp.FileRepository fileRepository;
#Before
public void setUp() throws IOException {
Files.deleteIfExists(basePath);
Files.createDirectories(basePath);
}
#After
public void after() throws IOException {
Files.deleteIfExists(basePath);
}
#Test
public void method() {
System.out.println(fileRepository.getBasePath());
}
}
If you use JUnit 5.4+ then you can leverage their #TempDir that works just fine without manual lifecycle management of the directory. That is you don't need to create and delete it manually, in contrast to #TemporaryFolder from JUnit 4.
Here is a working example of how you can achieve your goal:
//Your bean into which you want to inject the property
#Component
public class FileRepositoryManager {
#Value("${acme.fileRepository.basePath}")
private File basePath;
public File getBasePath() {
return basePath;
}
}
//Test that uses ApplicationContextInitializer machinery to set the desired properties
#SpringBootTest
#ContextConfiguration(initializers = Initializer.class)
class FileRepositoryManagerTest {
#TempDir
static File tempDir;
#Autowired
FileRepositoryManager fileRepositoryManager;
#Test
void basePathIsSet() {
assertNotNull(fileRepositoryManager.getBasePath());
}
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext context) {
TestPropertyValues.of(
"acme.fileRepository.basePath=" + tempDir
).applyTo(context);
}
}
}
I am new apache rest dsl with spring boot, have made following changes
Main Class
package com.javaoutofbounds.pojo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ccs.batchfile"})
public class BatchFileApplication {
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
}
Service class
package com.ccs.batchfile.service;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").produces("application/json").get("/routeStart").to("direct:startRoute");
}
}
Route class
package com.ccs.batchfile.routes;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ccs.batchfile.processor.StartRouteProcessor;
#Component
public class StartRoute extends RouteBuilder{
#Autowired
private StartRouteProcessor startRouteProcessor;
#Override
public void configure() throws Exception {
from("direct:startRoute").log("Inside StartRoute")
.process(startRouteProcessor);
}
}
Processor class
package com.ccs.batchfile.processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.springframework.stereotype.Component;
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor{
public void process(Exchange exchange) throws Exception {
String message = exchange.getIn().getBody(String.class);
System.out.println(message);
}
}
I am not getting control to StartRouteProcessor, when i make below post request in postman
http://localhost:8080/batchFile/routeStart/
I have used below test payload to check if works.
{
"title" : "test title",
"singer" : "some singer"
}
When i post the above request i am getting 404 error. Kindly help on this please
I tried your example and you need to add two changes.
In your "main" class, the 'component scan' annotation is right, but you have to add a 'ServletRegistrationBean' with name 'CamelServlet':
package org.funcode.app.main;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
#SpringBootApplication(scanBasePackages = {"org.funcode.app"})
public class BatchFileApplication {
private static final String CAMEL_URL_MAPPING = "/api/*";
private static final String CAMEL_SERVLET_NAME = "CamelServlet";
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean registration =
new ServletRegistrationBean(new CamelHttpTransportServlet(), CAMEL_URL_MAPPING);
registration.setName(CAMEL_SERVLET_NAME);
return registration;
}
}
And if you want view on the log the content you posted on the request, you need to change the method of the request to "post":
package org.funcode.app.main;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile")
.consumes("application/json")
.produces("application/json")
.post("/routeStart")
.to("direct:startRoute");
}
}
I hope it helps.
I try to run a testclass with the JUnit Platform Launcher. The Testclass contains some #Autowired Components. The issue is, that the injection doesn't seem to work. Is that even possible with JUnit Platform?
My code is as follows:
App.java
#SpringBootApplication(scanBasePackages = "com.mytests")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Component
import org.springframework.stereotype.Component;
#Component
public class SomeBean {
public String returnSuccess() {
return "SUCCESS";
}
}
Testclass
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class SomeTests {
#Autowired
private SomeBean aBean;
#Test
public void testSuccess() throws Exception {
String result = aBean.returnSuccess();
assertTrue(result.equals("SUCCESS"));
}
}
Controller which calls the test class
#RestController
public class TestController {
#RequestMapping("/tests")
public void executeTests() throws Throwable {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("com.mytests"), selectClass(SomeTests.class))
.build();
Launcher launcher = LauncherFactory.create();
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
listener.getSummary();
}
}
I have a parent class Car & a sub class Axio. So, i'm trying to pass an argument through super("Axio") within child constructor to constructor parameter in the parent class which then assign the value into a property defined within the parent class. When i try executing the application in spring boot it throws me an exception stating
Description:
Field car in com.test.efshop.controller.HelloController required a bean of type 'com.test.efshop.Axio' that could not be found.
Action:
Consider defining a bean of type 'com.test.efshop.Axio' in your configuration.
Can anyone please tell me how to achieve this in spring boot?. My Code is as below,
// Car class
package com.test.efshop;
public class Car {
private String carName;
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public Car(String carName) {
this.carName = carName;
}
public String print() {
return "Car name is : "+carName;
}
}
//sub class of car class which is Axio
package com.test.efshop;
public class Axio extends Car{
public Axio() {
super("Axio");
}
}
//main method
package com.test.efshop;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
//controller class
package com.test.efshop.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.test.efshop.Axio;
import com.test.efshop.Engine;
#Controller
public class HelloController {
#Autowired
private Axio car;
#RequestMapping(value = "/hello")
public ModelAndView print() {
return new ModelAndView("index");
}
//This is the method which i used to return the value of Car class
#RequestMapping(value = "/hello2")
#ResponseBody
public String print2() {
return car.print();
}
}
As pvpkiran commented, you can't #Autowire a class if it's not a Spring bean.
Option a) you convert the Axio class into a service or component.
#Component
public class Axio extends Car {
public Axio() {
super("Axio");
}
}
Option b) you define a bean of type Axio.
#SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public Axio myAxioBean() {
return new Axio();
}
}