I Have a Spring project. It works fine with junit test case. juint calls the applicationcontext.xml and the project run successfully. But i want to run the project without using jUnit.
Here is my jUnit Test Case
package com.dataload;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.util.StopWatch;
#ContextConfiguration(locations = "classpath:com/dataload/applicationcontext.xml")
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class SICSVDataTestCase {
private final static Logger logger = Logger
.getLogger(SICSVDataTestCase.class);
#Autowired
private JobLauncher launcher;
#Autowired
private Job job;
private JobParameters jobParameters = new JobParameters();
#Test
public void testLaunchJob() throws Exception {
StopWatch sw = new StopWatch();
sw.start();
launcher.run(job, jobParameters);
sw.stop();
logger.info(">>> TIME ELAPSED:" + sw.prettyPrint());
}
}
This testcase run the project. But i want to use another class that can call the applicationcontext.xml and run the project.
That is,
package com.dataload;
public class insertCSV
{
public static void main(String args[])
{
/* Code to run the project */
}
}
Can anyone suggest me how to code? Thanks
Add this at the start of main
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
JobLauncher launcher=(JobLauncher)context.getBean("launcher");
Job job=(Job)context.getBean("job");
//Get as many beans you want
//Now do the thing you were doing inside test method
StopWatch sw = new StopWatch();
sw.start();
launcher.run(job, jobParameters);
sw.stop();
//initialize the log same way inside main
logger.info(">>> TIME ELAPSED:" + sw.prettyPrint());
I am using in the way and it is working for me.
public static void main(String[] args) {
new CarpoolDBAppTest();
}
public CarpoolDBAppTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
Student stud = (Student) context.getBean("yourBeanId");
}
Here Student is my classm you will get the class matching yourBeanId.
Now work on that object with whatever operation you want to do.
package com.dataload;
public class insertCSV
{
public static void main(String args[])
{
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationcontext.xml");
// retrieve configured instance
JobLauncher launcher = context.getBean("laucher", JobLauncher.class);
Job job = context.getBean("job", Job.class);
JobParameters jobParameters = context.getBean("jobParameters", JobParameters.class);
}
}
Related
I want to create a daily background job to be executed by AEM.
I read an aem document and apache sling official site, and I thought I need two classes.
a service class that register the job to JobManager.
a consumer class that do the job.
So I tried these code, but my job was not executed.
service class
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobBuilder.ScheduleBuilder;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component
public class MyJobService {
private static final Logger logger = LoggerFactory.getLogger(MyJobService.class);
#Reference
private JobManager jobManager;
public static final String JOB_TOPIC = "my/sample/jobtopic";
public void startScheduledJob() {
ScheduleBuilder scheduleBuilder = jobManager.createJob(JOB_TOPIC).schedule();
scheduleBuilder.hourly(9, 0); // execute daily at AM9:00
if (scheduleBuilder.add() == null) {
logger.error("myjobservice error");
}
}
}
job consumer class
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component(
immediate = true,
service = JobConsumer.class,
property = {
JobConsumer.PROPERTY_TOPICS + "=my/sample/jobtopic"
}
)
public class MyJobConsumer implements JobConsumer {
private static final Logger logger = LoggerFactory.getLogger(MyJobConsumer.class);
#Override
public JobResult process(Job job) {
String topic = job.getTopic();
logger.info("this message is from myjobconsumer. topic is " + topic);
return JobResult.OK;
}
}
Do I need another class or some configurations? Does My code have something wrong?
If you annotate a method with #Activate it will be called when the component starts.
#Activate
public void startScheduledJob()
I guess you want your job to run on startup.
Another option would be to let MyJobService be a servlet and call it from outside.
I have specific instances that I need to use for autowiring in an AnnotationConfigWebApplicationContext. Below is the code that demonstrates the error. My case is much more complicated, of course, where the instances are determined at runtime. I discover the instances at spring configuration time which is why if the below coded worked, it would be fine. I tried but it throws NoSuchBeanDefinitionException even though ctx.getBean is able to find it. What's the right way to accomplish this?
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
class Scratch {
static class MyClass {
}
#Configuration
static class TestConfig {
#Autowired
private MyClass myClass;
}
public static void main(String[] args) {
MyClass requiredInstance = new MyClass();
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.refresh(); // Throws "BeanFactory not initialized..." on next line if this not here
ctx.getBeanFactory().registerSingleton("myClass", requiredInstance);
// Also tried: ((DefaultListableBeanFactory)ctx.getAutowireCapableBeanFactory()).registerSingleton("myClass", requiredInstance);
System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass#1804f60d"
ctx.register(TestConfig.class);
ctx.refresh(); // Throws "NoSuchBeanDefinitionException: No qualifying bean of type 'Scratch$MyClass' available:"
}
}
Found a solution here https://blog.pchudzik.com/201705/dynamic-beans/ . I had seen BeanFactoryPostProcessor mentioned elsewhere but they didn't show how to create the instance. This example showed using the factory mechanism that is what I needed.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
class Scratch {
static class MyClass {
}
#Configuration
static class TestConfig {
#Autowired
private MyClass myClass;
}
public static void main(String[] args) {
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(TestConfig.class);
ctx.register(DynamicBeanFactoryProcessor.class);
ctx.refresh();
System.out.println(ctx.getBean("myClass")); // Outputs "Scratch$MyClass#1804f60d"
System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass#1804f60d"
}
#Configuration
public static class DynamicBeanFactoryProcessor implements BeanFactoryPostProcessor {
public <T> T createInstance(Class<T> c) {
return c.cast(new MyClass()); // Create dynamic instance here
}
#Bean
public DynamicBeanFactoryProcessor dynamicBeanFactoryProcessor() {
return new DynamicBeanFactoryProcessor();
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
((BeanDefinitionRegistry)beanFactory).registerBeanDefinition("myClass",
BeanDefinitionBuilder.genericBeanDefinition(MyClass.class)
.setFactoryMethodOnBean("createInstance", "dynamicBeanFactoryProcessor")
.addConstructorArgValue(MyClass.class)
.getBeanDefinition());
}
}
}
I have an ItemProcessor which has a #BeforeStep method to access the ExecutionContext:
public class MegaProcessor implements ItemProcessor<String, String> {
private ExecutionContext context;
#BeforeStep
void getExecutionContext(final StepExecution stepExecution) {
this.context = stepExecution.getExecutionContext();
}
#Override
public String process(final String string) throws Exception {
// ...
}
}
The unit test for this class:
#ContextConfiguration(classes = MegaProcessor.class)
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
#RunWith(SpringRunner.class)
public class MegaProcessorTest {
#Autowired
private MegaProcessor sut;
public StepExecution getStepExecution() {
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
execution.getExecutionContext().put("data", "yeah");
return execution;
}
#Test
public void MegaProcessor() throws Exception {
assertNotNull(sut.process("pew pew"));
}
}
When I debug the test run, context is null and the #BeforeStep method is never called. Why is that and how to achieve that?
Why is that
If you want to use the StepScopeTestExecutionListener, the tested component should be step-scoped (See Javadoc). It's not the case in your example. But this is not the real issue. The real issue is that the method annotated with #BeforeStep will be called before the step in which your processor is registered is executed. In your test case, there is no step running so the method is never called.
how to achieve that?
Since it is a unit test, you can assume the step execution will be passed to your item processor by Spring Batch before running the step and mock/stub it in your unit test. This is how I would unit test the component:
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.StepExecution;
import static org.junit.Assert.assertNotNull;
public class MegaProcessorTest {
private MegaProcessor sut;
#Before
public void setUp() {
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
execution.getExecutionContext().put("data", "yeah");
sut = new MegaProcessor();
sut.getExecutionContext(execution); // I would rename getExecutionContext to setExecutionContext
}
#Test
public void MegaProcessor() throws Exception {
assertNotNull(sut.process("pew pew"));
}
}
The StepScopeTestExecutionListener is handy when you have step-scoped components that use late-binding to get values from the step execution context. For example:
#Bean
#StepScope
public ItemReader<String> itemReader(#Value("#{stepExecutionContext['items']}") String[] items) {
return new ListItemReader<>(Arrays.asList(items));
}
A unit test of this reader would be something like:
import java.util.Arrays;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
#ContextConfiguration(classes = StepScopeExecutionListenerSampleTest.MyApplicationContext.class)
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
#RunWith(SpringRunner.class)
public class StepScopeExecutionListenerSampleTest {
#Autowired
private ItemReader<String> sut;
public StepExecution getStepExecution() {
StepExecution execution = MetaDataInstanceFactory.createStepExecution();
execution.getExecutionContext().put("items", new String[] {"foo", "bar"});
return execution;
}
#Test
public void testItemReader() throws Exception {
Assert.assertEquals("foo", sut.read());
Assert.assertEquals("bar", sut.read());
Assert.assertNull(sut.read());
}
#Configuration
static class MyApplicationContext {
#Bean
#StepScope
public ItemReader<String> itemReader(#Value("#{stepExecutionContext['items']}") String[] items) {
return new ListItemReader<>(Arrays.asList(items));
}
/*
* Either declare the step scope like the following or annotate the class
* with `#EnableBatchProcessing` and the step scope will be added automatically
*/
#Bean
public static org.springframework.batch.core.scope.StepScope stepScope() {
org.springframework.batch.core.scope.StepScope stepScope = new org.springframework.batch.core.scope.StepScope();
stepScope.setAutoProxy(false);
return stepScope;
}
}
}
Hope this helps.
According to Quratz documentation2.x Here
If you add setter methods to your job class that correspond to the names of keys in the JobDataMap (such as a setJobSays(String val) method for the data in the example above), then Quartz’s default JobFactory implementation will automatically call those setters when the job is instantiated, thus preventing the need to explicitly get the values out of the map within your execute method.
Now in my case the setters are not automatically called although my all values are primitives. Also in execute method i am able to get values from jobDataMap.
i am using Quartz 2.2.1 and here is my sample code.what should i do ? thanks in advance.
Here is my Job class.
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
public class Db2Db implements Job {
public static final String SOURCE_HOST = "sourceHost";
public static final String DESTINATION_HOST = "destinationHost";
protected String sourceHost;
protected String destinationHost;
public Db2Db() {
System.out.println("created object of job");
}
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//sourceHost is still null
system.out.println(sourceHost);
}
public void setSourceHost(String sourceHost) {
this.sourceHost = sourceHost;
}
public void setDestinationHost(String destinationHost) {
this.destinationHost= destinationHost;
}
}
and Here is my main method
public class JobDriver {
public static void main(String[] args) throws SchedulerException {
/*Starting quartz server remotely*/
QuartzServer server = QuartzServer.getInstance();
server.start();
JobDetail job = newJob(Db2Db.class)
.usingJobData(SOURCE_HOST, "132.168.0.12")
.usingJobData(DESTINATION_HOST, "localhost")
.withIdentity("DailyRead91", "group1")
.build();
Trigger trigger = newTrigger().withIdentity("DailyTrigger91", "group1").startNow()
.withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatForever()).build();
//Quartz Server Properties
Properties prop = new Properties();
prop.put("org.quartz.scheduler.rmi.proxy", "true");
prop.put("org.quartz.scheduler.rmi.registryHost", "localhost");
prop.put("org.quartz.scheduler.rmi.registryPort", "1099");
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "10");
Scheduler scheduler = new StdSchedulerFactory(prop).getScheduler();
scheduler.scheduleJob(job, trigger);
}
}
I want to do an integration test on my SpringMVC application using Selenium, with something like:
#Test
public void mytest() {
WebDriver driver = new FirefoxDriver();
driver.get("localhost:8080/myapp/mycontroller");
List<WebElement> elements = driver.findElements(By.cssSelector(".oi"));
assertThat(elements, hasSize(1));
}
Is it possible to "run" my app, the same way that my mvn tomcat7:run would do, and then perform my selenium tests?
Update:
I'm using Spring 4.0.x. I already have Unit Tests for every classes on my webapp, but I need an Integration Test. My controllers are already being tested with MockMVC and spring-test-framework... but I would like to do a selenium integration test.
After a lot o tries, i ended up with a base class for my Selenium Integration tests:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.openqa.selenium.firefox.FirefoxDriver;
import static io.github.seleniumquery.SeleniumQuery.$;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class SeleniumAcceptanceTest {
private static final String WEBAPP_FOLDER = "../../src/main/webapp";
private static final String APP_CONTEXT = "/myapp";
private static final int ANY_RANDOM_PORT_AVAIABLE = 0;
static Server server;
protected static String urlBase;
#BeforeClass
public static void prepareTests() throws Exception {
startWebAppServer();
$.browser.setDefaultDriver(new FirefoxDriver());
}
#AfterClass
public static void finalizaTests() {
$.browser.quitDefaultBrowser();
}
private static void levantarServidorDeAplicacao() throws Exception {
server = new Server(QUALQUER_PORTA_DISPONIVEL);
String rootPath = SeleniumAcceptanceTest.class.getClassLoader().getResource(".").toString();
WebAppContext webapp = new WebAppContext(rootPath + WEBAPP_FOLDER , "");
webapp.setContextPath(APP_CONTEXT );
server.setHandler(webapp);
server.start();
while (true) {
if (server != null && server.isStarted()) {
break;
}
}
int port = server.getConnectors()[0].getLocalPort();
urlBase = "http://localhost:" + port + APP_CONTEXT ;
}
}
And then, a test class extends this class:
public class AlertasAcceptanceTest extends SeleniumAcceptanceTest {
#Test
public void alertas_index__must_show_table_with_4_lines() {
//given
doLogin();
//when
$.browser.openUrl(urlBase + "/alertas/" );
int linesInTheTable = $("table tr").size();
//then
assertThat(linesInTheTable , is(4));
}
}
I hate answering a question with a question, but... 1) do you have to use Selenium or could it be a jUnit test? 2) which version of Spring MVC do you use? Spring 3.2 added a VERY neat feature that lets you spin up mock MVC and execute HTTP requests against it. This way you don't have to worry about starting/stopping your server and all your tests are done from "within" the app itself. Here is a snippet:
#Test
public void addAsUser() throws Exception {
TodoDTO added = TodoTestUtil.createDTO(null, "description", "title");
mockMvc.perform(post("/api/todo")
.contentType(IntegrationTestUtil.APPLICATION_JSON_UTF8)
.content(IntegrationTestUtil.convertObjectToJsonBytes(added))
.with(userDetailsService("user"))
)
.andExpect(status().isOk())
.andExpect(content().contentType(IntegrationTestUtil.APPLICATION_JSON_UTF8))
.andExpect(content().string("{\"id\":3,\"description\":\"description\",\"title\":\"title\"}"));
}
Full article can be found here.