How to call a spring controller after all the bean get initialized?
I used ServletContextListener and tried to call one controller. But, it doesn't exixts since all the bean initialization are getting invoked after the contextInitialized method execution.
I'm loading one variable from db, in the application context which has some global value. That action has to be triggered once the application is deployed immediately.
What needs to be done?
You can use the #PostConstruct phase to simulate context initialization completion.
I assume you want to invoke methods on ControllerA, ControllerB and store the results of those method invocations elsewhere on app start up.
public class InitializationHook {
private ControllerA controllerA;
private ControllerB controllerB;
#Autowired
public InitializationHook(ControllerA controllerA, ControllerB controllerB) {
this.controllerA = controllerA;
this.controllerB = controllerB;
}
#PostConstruct
public void init() {
//do whatever you want with both the controllers
controllerA.getGlobalValueFromDB();
controllerB.doSomethingElse();
/*
* At this point, controllerA and controllerB would have been initialized completely
* along with their dependencies (could be connections to DB etc) and ready for use.
* You don't have to worry about the other beans getting initialized.
*/
}
}
When you want to execute some piece of code exactly before the application startup completes, you can CommandLineRunner.
#Component
public class ControllerRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(ControllerRunner.class);
#Override
public void run(String...args) throws Exception {
logger.info("Your application has been started");
//TODO - call your controller
}
}
I achieved my requirement using below code:
#WebListener
public class StartUpListener implements ServletContextListener {
private static final Logger logger = Logger.getLogger(StartUpListener.class);
#Override
public void contextInitialized(ServletContextEvent sce) {
logger.info("********* context Refreshed **********");
new Thread(new Runnable() {
public void run(){
try {
TimeUnit.SECONDS.sleep(10);
URL url = new URL ("http://localhost:8080/myapp/loadFeature");
URLConnection con = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
logger.info(inputLine);
}
in.close();
} catch (Exception e) {
logger.error(e);
}
}
}).start();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("********* context contextDestroyed **********");
}
}
Related
I have started a thread but when it try to access entity Manager it throws exception as
javax.enterprise.context.ContextNotActiveException:
WebBeans context with scope type annotation #RequestScoped does not exist within current thread
How should I access EntityManger with thread
any solution?
public class SchedulerForData {
#Inject
private DefaultUserSevice userSevice;
public void beepForAnHour() {
long initialDelay;
final Runnable beeper = new Runnable() {
public void run() {
userSevice.getData();
}
scheduler.scheduleAtFixedRate(beeper, 60, 30, TimeUnit.SECONDS);
}
}
}
public class DefaultUserSevice {
#Inject
EntityManager entityManger;
public void getData(){
List resultList = entityManager.createNativeQuery("Select * from USER").getResultList();
}
}
If there is no other configuration on the service, you should make the service a managed bean and add transactional feature:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class DefaultUserSevice
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 want to test the code below with Mockito
#Override
public void getSessionList(final int carId, final ResultCallback<List<Session>> callback) {
jobExecutor.execute(new Runnable() {
#Override
public void run() {
List<SessionEntity> sessions = IDataStore.getSessionList(carId);
final List<Session> sessionList = new ArrayList<>();
if (sessions != null) {
for (SessionEntity entity : sessions) {
sessionList.add(mapper.transform(entity));
}
uiThread.post(new Runnable() {
#Override
public void run() {
if (callback != null) {
callback.onResult(sessionList);
}
}
});
}
}
});
}
I tried to do something like this, but my verify methods will be executed early than runnable.
Thread.sleep() works well for the first two verify, but how to test the result from callback.onResult which will be executed in the main thread?
private Repository repository // not mocked
#Mock
private IDataStore dataStore;
#Mock
private DataToDomainMapper dataToDomainMapper;
#Mock
private ResultCallback resultCallback;
#Test
public void testGetSessionListCallbackSuccess(){
List<SessionEntity> sessionEntities = Arrays.asList(sessionEntity, sessionEntity, sessionEntity);
given(dataStore.getSessionList(anyInt())).willReturn(sessionEntities);
given(dataToDomainMapper.transform(any(SessionEntity.class))).willReturn(session);
repository.getSessionList(1, resultCallback);
verify(dataStore).getSessionList(anyInt());
verify(dataToDomainMapper, times(3)).transform(any(SessionEntity.class));
verify(resultCallback).onResult(any(List.class));
}
Check out tool for testing async methods called Awaitility. Very handy tool, saved me a lot of time on testing async methods.
I believe you can move anonymous Runnable to inner (or nested) class and split testing on two parts: check that jobExecutor started execution with corresponding class instance and check that run() method of your inner/nested class works as you expect
I have an application built upon Spring Boot. There is simple controller with a method which creates new Thread and starts it. However a runnable executes unix command (nc) (used ProcessBuilder for that). Thus when I'm runnning it on the windows I get exceptions from started thread. Indeed it can not run unix program. Now I would like to write a test for this controller, but I'm wondering is it possible and reasonable. I was thinking about changing behaviour of runnable task just for testing, although I don't know how can it be done. Thanks for any help and other ideas/solutions for this case.
Controller:
#Controller
public class TaskController {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(task-%d").build();
#RequestMapping(value = "/startTask")
public #ResponseBody ResponseEntity<String> startTask() {
Runnable runnable= new Task();
threadFactory.newThread(runnable).start();
return new ResponseEntity<String>("Task started", HttpStatus.ACCEPTED);
}
}
Task:
public class Task implements Runnable {
#Override
public void run() {
// start unix process
}
}
Application class:
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Integration Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest("server.port=0")
#DirtiesContext
public class ApplicationTest {
#Value("${local.server.port}")
private int port;
#Test
public void shouldStartTask() throws Exception {
// when
ResponseEntity<String> entity = new TestRestTemplate().getForEntity("http://localhost:" + this.port + "/startTask", String.class);
// then
assertThat(entity.getStatusCode()).isSameAs(HttpStatus.ACCEPTED);
}
}
You might find it easier to test your program if you the extract the processing logic of your application (which does things using threads) from your controller logic, placing the processing logic in a separate service layer, which your controller delegates to. Design the service layer to have an API that is easy to unit test, by providing methods for accessing its current state, not just for performing actions. Use dependency injection to connect your controller to your service layer.
So, something like this:
public interface Service
{
// Sets this.wasTaskStarted() == true
void startTask();
boolean wasTaskStarted();
void awaitCompletionOfTask();
}
#Controller
public class TaskController {
private final Service service;
#Autowired
public TaskController(Service service) {
this.service = service;
}
#RequestMapping(value = "/startTask")
public #ResponseBody ResponseEntity<String> startTask() {
service.startTask();
return new ResponseEntity<String>("Task started", HttpStatus.ACCEPTED);
}
}
public ServiceImpl implements Service {
private final ThreadFactor threadFactory = new ....;
private Thread taskTread;
#Override
public synchronized void startTask() {
if (taskTread == null) {
taskTread = threadFactory.newThread(new Task());
taskTread.start();
notifyAll();
}
// else already started
}
#Override
public synchronized boolean wasTaskStarted() {
return taskTread != null;
}
#Override
public synchronized void awaitCompletionOfTask() {
while (taskTread == null) {
wait();
}
taskTread.join();
}
}
To test that your controller starts a task, you just need to test that Service.wasTaskStarted() is true after calling TaskController.startTask().
You also have to test your service layer:
public class ServiceImplTest
{
#Test
public void testStartTask() {
final ServiceImpl service = new ServiceImpl(....);
service.startTask();
assert(service.wasTastStarted());
}
#Test
public void testRunTask() {
final ServiceImpl service = new ServiceImpl(....);
service.startTask();
service.awaitCompletionOfTask();
// Add assertions here to test that the task did what it ought to do
}
}
Thanks for the suggestion. You just opened my mind and I changed the design a bit. I resigned from an integration test. From business point of view, I don't need to check whether task has been started or even completed. Now it looks as follows:
Controller:
#Controller
public class TaskController {
private ThreadService threadService;
#Autowired
public TaskController (ThreadService threadService) {
this.threadService= threadService;
}
#RequestMapping(value = "/startTask")
public #ResponseBody ResponseEntity<String> startTask() {
// some conditions here which I would like to test
threadService.startNewThread(new Task());
return new ResponseEntity<String>("Task started", HttpStatus.ACCEPTED);
}
}
Task:
public class Task implements Runnable {
#Override
public void run() {
// start unix process
}
}
Thread service:
#Component
public class ThreadService {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("task-%d").build();
public void startNewThread(Runnnable task) {
threadFactory.newThread(task).start();
}
}
And I decided to unit test my controller, stubbing ThreadService with mockito:
#RunWith(MockitoJUnitRunner.class)
public class TaskControllerTest {
#Mock
ThreadService threadService;
#InjectMocks
private TaskController objectUnderTest;
#Test
public void shouldStartTask() throws FileNotFoundException {
// when
ResponseEntity<String> response = objectUnderTest.startTask();
// then
assertThat(response.getStatusCode()).isSameAs(HttpStatus.ACCEPTED);
// more assertions
}
I have created an actor which extends UnTypedProcessor. I intend to use this actor to persist some of it's messages to disk. The actor looks like so,
public class Shard extends UntypedProcessor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
#Override
public void onReceive(Object message) throws Exception {
if(message instanceof CreateTransactionChain) {
System.out.println("Received a CreateTransactionChain message");
ActorRef transactionChain = getContext().actorOf(Props.create(TransactionChain.class), "transactionChain");
Address address = transactionChain.path().address();
getSender().tell(new CreateTransactionReply(address), getSelf());
}
}
}
I have a unit test written for this like so,
public class ShardTest extends AbstractActorTest{
#Test
public void testOnReceiveCreateTransaction() throws Exception {
System.out.println("running tests");
new JavaTestKit(getSystem()) {{
final Props props = Props.create(Shard.class);
final TestActorRef<Shard> subject = TestActorRef.create(getSystem(), props, "test");
// can also use JavaTestKit “from the outside”
final JavaTestKit probe = new JavaTestKit(getSystem());
// the run() method needs to finish within 3 seconds
new Within(duration("3 seconds")) {
protected void run() {
subject.tell(new CreateTransactionChain(), getRef());
final String out = new ExpectMsg<String>("match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in instanceof CreateTransactionReply) {
return "match";
} else {
throw noMatch();
}
}
}.get(); // this extracts the received message
assertEquals("match", out);
// Will wait for the rest of the 3 seconds
expectNoMsg();
}
};
}};
}
}
When I run this test the onReceive method of the UntypeProcessor does not get invoked. If I extended my class from UntypedActor instead things work just fine. Any ideas why extending UntypedProcessor does not work? Is there some configuration I need to add to get this to work? Is there something that needs to be mocked?
akka-persistence does not work with the same thread dispatcher which is what the TestActorRef provides. We need to switch to using a simple ActorRef so that a multithreaded dispatcher can be used for the test.
This github issue talks about the very same problem :- https://github.com/akka/akka/issues/15293