I am trying to create an application which will be used only in particular cases, from time to time.
scenario is as follows
user run an application
aplication start with spring-context.xml camel-context.xml
Routes from AppRoute.java are created
method which use created routes are executed
end
However I have a problem because whenever I use main.run() I can see that route is created however method is not executed. Without main.run() method is executed but no route is built.
my main:
import org.apache.camel.spring.Main;
import org.springframework.stereotype.Component;
public class EgzekutorManual extends Main{
#Produce(uri="direct:tester")
static ProducerTemplate pt;
public static void main(String[] args) throws Exception {
Main main = new Main();
main.showOptions();
main.run();
main.addRouteBuilder(new AppRoute());
manualTester();
}
public void manualTester(){
System.out.println("Manual tester executed");
pt.sendBody("X");
}
}
AppRoute.java:
private static class AppRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:tester")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Tester received message");
}
});
}
}
Can anyone give me a hint what I am doing wrong?
Related
I am trying to execute a method in a separate thread, when the server starts. Please find my main class below:
#SpringBootApplication
#EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
#Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(new CsvReader());
}
};
}
}
#Component
public class CsvReader implements Runnable{
#Value("${file-url}")
private String appUrl;
#Override
public void run() {
System.out.println("run after Object created: "+ appUrl); // this is coming as null. Not able to read it from application.properties
}
}
You can use #PropertySource annotation.
Something like this
#SpringBootApplication
#PropertySource("application.properties")
#EnableSwagger2
public class Application {
// Your code
}
You can Autowire the value like this
#Component
public class CsvReader implements Runnable{
#Value("${property.name.from.application.properties.file}")
private String appUrl;
#Override
public void run() {
System.out.println("run after Object created: "+ appUrl); // this is coming as null. Not able to read it from application.properties
}
}
Got the issue,
As I am executing CsvReader in a separate thread, container is not taking care of the bean initialisation, and thus dependency injections are not working.
Fixed the issue by
#Configuration
public class CsvReader {
#Value("${file-url}")
private String appUrl;
#PostConstruct
private void runAfterObjectCreated() {
Thread thread = new Thread() {
public void run() {
System.out.println("run after Object created: "+ appUrl);
}
};
thread.start();
}
}
With the above code, I am delegating the bean instantiation to the container.
#PostConstruct, ensures execution, once the class is loaded, and because I have a Thread class instantiated, by method is running in a new thread.
Option 2
#SpringBootApplication
#EnableSwagger2
public class Application {
#Autowired
private CsvReader csvReader;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(csvReader);
}
};
}
}
I am tasked with making our database writes asynchronous. Sounds pretty simple on the surface, but the info I'm getting online isn't all that helpful and what I hear from co-workers is "asynch is tricky". So, I'm hoping to get something more helpful than "play with it bit until you get it to work". My code/call looks like this:`
#EnableAsync
#SpringCloudApplication
//To run as a FAT JAR:
//public class Application {
// Only extend when running as WAR
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}}
public class MyClass{
public void asyncCall(){
if(1==1){
DatabaseWriter.testAsync();
System.out.println("past DatabaseWriter.testAsync() method");
return;
}
}}
public class DatabaseWriter {
#Async
public static Future<Object> testAsync(){
Thread.sleep(10000);
println ("end of DatabaseWriter.testAsync() method");
return null;
}}
`
So, my output consistently comes out looking like this:
end of DatabaseWriter.testAsync() method
past DatabaseWriter.testAsync() method
Obviously, the original method call is waiting for the return from the testAsync() method. I'm looking for direction on what I'm doing wrong.
#Async annotation works only for beans from the spring context, because spring creates proxy around async method. So if you create bean with new keyword:
new DatabaseWriter();
or if you put #Async annotation on static method it will not work, because there will be original method instead of proxy.
That example works well. To start the application just run the main method
#SpringBootApplication
#EnableAsync
public class Application extends AsyncConfigurerSupport {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("GithubLookup-");
executor.initialize();
return executor;
}
}
#Component
class AppRunner implements CommandLineRunner {
public static final Logger logger = LoggerFactory.getLogger(AppRunner2.class);
#Autowired
private DatabaseWriter writer;
#Override
public void run(String... args) throws Exception {
logger.info("--- start ---");
writer.testAsync();
logger.info("--- stop ---");
}
}
#Component
class DatabaseWriter {
#Async
public Future<Object> testAsync() throws InterruptedException {
Thread.sleep(5000);
AppRunner.logger.info("end of DatabaseWriter.testAsync() method");
return null;
}
}
You can try to replace line
writer.testAsync();
with
new DatabaseWriter().testAsync();
and will see that the #Async doesn't work.
I am new to Apache Camel and trying to receive a simple SNMP trap.
I have the Maven project set up with camel-core and org.apache.servicemix.bundles.snmp4j.
I have not been able to find any SNMP examples, but based on other examples I have come up with this Main class:
public class Main {
public static Processor myProcessor = new Processor() {
public void process(Exchange arg0) throws Exception {
// save to database
}
};
public static void main(String[] args) {
CamelContext context = new DefaultCamelContext();
context.addComponent("snmp", new SnmpComponent());
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("snmp:127.0.0.1:162?protocol=udp&type=TRAP").process(myProcessor);
}
};
try {
context.addRoutes(builder);
context.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
However when I run it in Eclipse as Java application it just exits after running for half a second. I was expecting it to keep running and listening to 127.0.0.1:162 ...
Any help is greatly appreciated
One way to at least pick up a trap and print to System.out is like so:
public class SNMPTrap {
private Main main;
public static void main(String[] args) throws Exception {
SNMPTrap snmpTrap = new SNMPTrap();
snmpTrap.boot();
}
#SuppressWarnings("deprecation")
public void boot() throws Exception {
main = new Main();
main.bind("snmp", new SnmpComponent());
main.addRouteBuilder(new MyRouteBuilder());
main.addMainListener(new Events());
System.out.println("Starting SNMPTrap. Use ctrl + c to terminate the JVM.\n");
main.run();
}
private static class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("snmp:127.0.0.1:162?protocol=udp&type=TRAP").process(myProcessor)
.bean("snmp");
}
}
public static Processor myProcessor = new Processor() {
public void process(Exchange trap) throws Exception {
System.out.println(trap.getIn().getBody(String.class));
// Save to DB or do other good stuff
}
};
public static class Events extends MainListenerSupport {
#Override
public void afterStart(MainSupport main) {
System.out.println("SNMPTrap is now started!");
}
#Override
public void beforeStop(MainSupport main) {
System.out.println("SNMPTrap is now being stopped!");
}
}
}
However, I get warning that Main which is part of Camel core is deprecated now.
I am trying to write a TestNgtest case for a console app for when the user inputs ESC. At which point the application should print a message and then exit. I want the TestNg to test if the message gets printed. Here's the app code:
public class Application {
public static void doSomething(Scanner scanner) {
String inputString = scanner.nextLine();
if("ESC".equals(inputString.toUpperCase())) {
System.out.println("Bye");
System.exit(0);
}
}
}
Here's the junit code:
public class ApplicationTest {
private Application app;
private ByteArrayInputStream in;
private ByteArrayOutputStream out;
#BeforeMethod
public void setUp() throws Exception {
app = new Application();
out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
}
#AfterMethod
public void tearDown() throws Exception {
System.setIn(System.in);
}
#Test
public void testESCInput() throws Exception {
in = new ByteArrayInputStream("ESC".getBytes());
System.setIn(in);
app.processInput(new Scanner(System.in));
assertTrue(out.toString().contains("Bye"));
}
}
But since the application exits with System.exit I don't even get to the assertTrue line, the TestNg just ends before that. Is there a right way to test this?
You can use a SecurityManager to reject exit attempts, then build tests around the expected exception, e.g. this works with JUnit, should be easily adapted to TestNG
public class ExitTest {
public static class RejectedExitAttempt extends SecurityException {
private int exitStatus;
public RejectedExitAttempt(int status) {
exitStatus=status;
}
public int getExitStatus() {
return exitStatus;
}
#Override
public String getMessage() {
return "attempted to exit with status "+exitStatus;
}
}
#Before
public void setUp() throws Exception {
System.setSecurityManager(new SecurityManager() {
#Override
public void checkPermission(Permission perm) {
if(perm instanceof RuntimePermission && perm.getName().startsWith("exitVM."))
throw new RejectedExitAttempt(
Integer.parseInt(perm.getName().substring("exitVM.".length())));
}
});
}
#After
public void tearDown() throws Exception {
System.setSecurityManager(null);
}
#Test(expected=RejectedExitAttempt.class)
public void test() {
System.exit(0);
}
}
This is a simple test, that is satisfied with any exit attempt. If a particular exit status is required, you have to catch the exception and verify the status.
Since this custom SecurityManager allows any other action, resetting the security manager to null is possible.
I'm using ElasticMQ to test classes which use AWS SQS. Because my unit tests are atomic I'd like to ensure that the SQS queue on which they operate is empty at the start of every test. However, as ElasticMQ is asynchronous and non-blocking, this can't be ensured before every test. Is there any way to set the behaviour of ElasticMQ (or even just purgeQueue) to be blocking? I'm currently using embedded ElasticMQ. Here's an example of my test class which runs into this issue:
public class QueuerTest extends AbstractServiceTest {
private static ASyncConsumerService<String> aSyncConsumerService = new ASyncConsumerService<>(QueueName.VALID);
private static Queuer queuer = new Queuer();
private static SQSRestServer server = SQSRestServerBuilder.start();
#BeforeClass
public static void beforeClass() {
queuerTest.init();
aSyncConsumerService.setEndpoint("http://localhost:9324");
}
#Before
public void before() {
aSyncConsumerService.purgeQueue();
}
#AfterClass
public static void afterClass() {
server.stopAndWait();
}
#Test
public void testWriteValid() {
queuer.writeDataToQueueIfValid("valid");
assertEquals("valid", aSyncConsumerService.receive());
}
#Test
public void testWriteInvalid() {
queuer.writeDataToQueueIfValid("invalid");
assertNull(aSyncConsumerService.receive(1000));
}
}