Schedule JPA query and access result in a CDI-bean? - jpa-2.0

Every x minutes I want to query for new instances and cache the results. I currently only need a simple cache solution so I would like to update a Set in my #ApplicationScoped CacheBean
I tried a:
ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
ScheduledFuture<?> sf = scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
//.................
But the thread created couldn't access any contextual instances (InvocationException).
So how to do this the CDI/JPA way?
Using Tomcat 7, Weld, JPA2 - Hibernate.

My recommendation would be to try the version of Tomcat with CDI and JPA already integrated (TomEE). It comes with OpenJPA but you can use Hibernate. Then do your caching with a class like this:
#Singleton
#Startup
public class CachingBean {
#Resource
private BeanManager beanManager;
#Schedule(minute = "*/10", hour = "*")
private void run() {
// cache things
}
}
That component would automatically start when the app starts and would run the above method every ten minutes. See the Schedule docs for details.
UPDATE
Hacked up an example for you. Uses a nice CDI/EJB combination to schedule CDI Events.
Effectively this is a simple wrapper around the BeanManager.fireEvent(Object,Annotations...) method that adds ScheduleExpression into the mix.
#Singleton
#Lock(LockType.READ)
public class Scheduler {
#Resource
private TimerService timerService;
#Resource
private BeanManager beanManager;
public void scheduleEvent(ScheduleExpression schedule, Object event, Annotation... qualifiers) {
timerService.createCalendarTimer(schedule, new TimerConfig(new EventConfig(event, qualifiers), false));
}
#Timeout
private void timeout(Timer timer) {
final EventConfig config = (EventConfig) timer.getInfo();
beanManager.fireEvent(config.getEvent(), config.getQualifiers());
}
// Doesn't actually need to be serializable, just has to implement it
private final class EventConfig implements Serializable {
private final Object event;
private final Annotation[] qualifiers;
private EventConfig(Object event, Annotation[] qualifiers) {
this.event = event;
this.qualifiers = qualifiers;
}
public Object getEvent() {
return event;
}
public Annotation[] getQualifiers() {
return qualifiers;
}
}
}
Then to use it, have Scheduler injected as an EJB and schedule away.
public class SomeBean {
#EJB
private Scheduler scheduler;
public void doit() throws Exception {
// every five minutes
final ScheduleExpression schedule = new ScheduleExpression()
.hour("*")
.minute("*")
.second("*/5");
scheduler.scheduleEvent(schedule, new TestEvent("five"));
}
/**
* Event will fire every five minutes
*/
public void observe(#Observes TestEvent event) {
// process the event
}
}
Full source code and working example, here.
You must know
CDI Events are not multi-treaded
If there are 10 observers and each of them take 7 minutes to execute, then the total execution time for the one event is 70 minutes. It would do you absolutely no good to schedule that event to fire more frequently than 70 minutes.
What would happen if you did? Depends on the #Singleton #Lock policy
#Lock(WRITE) is the default. In this mode the timeout method would essentially be locked until the previous invocation completes. Having it fire every 5 minutes even though you can only process one every 70 minutes would eventually cause all the pooled timer threads to be waiting on your Singleton.
#Lock(READ) allows for parallel execution of the timeout method. Events will fire in parallel for a while. However since they actually are taking 70 minutes each, within an hour or so we'll run out of threads in the timer pool just like above.
The elegant solution is to use #Lock(WRITE) then specify some short timeout like #AccessTimeout(value = 1, unit = TimeUnit.MINUTES) on the timeout method. When the next 5 minute invocation is triggered, it will wait up until 1 minute to get access to the Singleton before giving up. This will keep your timer pool from filling up with backed up jobs -- the "overflow" is simply discarded.

Instead of passing new Runnable() {....} into scheduler.scheduleAtFixedRate rather create a CDI bean that implements Runnable and #Inject that bean and then pass it to scheduler.scheduleAtFixedRate

After chatting with David Blevins for a good while I can acknowledge his answer as a great one that I voted up. Big thanks for all that. All though David you forgot to announce your involvement in TomEE which I know always bother someone.
Anyways the solution I went for was suggested by Mark Struberg in #Deltaspike (freenode).
As a deltaspike user I was pleased to do it with deltaspike. Solution is outlined in this blog post:
http://struberg.wordpress.com/2012/03/17/controlling-cdi-containers-in-se-and-ee/
I had to switch into OWB see https://issues.apache.org/jira/browse/DELTASPIKE-284
Cheers

Related

Guava's AsyncEventBus in tests

In our code messages travelling on guava's AsyncEventBus are frequently used. Now, in some of the tests some message traffic needs to finish, before assert on the state of the testee (say, some loads are scheduled on the EventBus, and these need to finish, so that we can test if things were loaded correctly).
Unfortunately, at the moment this is handled by the horrible Thread.sleep(delay); approach; very fragile and making tests flaky.
What would be the proper way to test code depending on completion of operations on common AsyncEventBus?
What I do in end-to-end or integration tests (multiple threads involved) where I need to wait until an event occurred is using a CountDownLatch. I would stay far away from sleeping threads as you've already mentioned.
This requires that in your test code you can hook the CountDownLatch.countDown() method into the callback method the EventBus is going to call. I explain that with a short example:
class SomeEventReceiver {
...
#Subscribe public void doSomethingFoo(BarEvent e) {
// your logic
}
...
}
// Unit test
...
CountDownLatch readyToAssert = new CountDownLatch(1); // could be 2 or more depending on your needs
SomeEventReceiver rec = new SomeEventReceiver(...) { // create an anonymous subclass
#Subscribe
#Override
public void doSomethingFoo(BarEvent e) { // override super method
super.doSomethingFoo(e); // execute super method's logic
readyToAssert.countDown(); // signal your test method that it's ready to assert
}
}
// put your events on the event bus and do all other necessary things
...
readyToAssert.await(); // JUnit thread is blocked until event handlers where called
assertXXX(...); // assert whatever needs to be asserted
That's my firsthand approach when testing. Obviously it's easier to do if the to-be-tested classes are designed in a testfriendly manner.
Hope that helped!

how to run one or group of tests repeatedly in Go Test IntelliJ

From time to time I have this annoying tests with intermittent issues, that I need to run many times to expose. I was looking for a convenient way to set a number or "endless loop" from the intelliJ, but I did not find.
Is there a plugin or I missed something that could allow me to do this from the UI (instead of changing code for it).
EDIT: As I found the support for such feature is per test utility plugin. For example, it already exists for JUnit, but there is no such for Go Test. My instinct suggests that such functionality should be generically provided for all test plugins, but there might be some technical reasons for per plugin approach.
In the Run Configuration of the test there is a "Repeat:" dropdown where you can specify the number of repeats, for example until the test fails. I believe this is available since IntelliJ IDEA 15.
You can use oracle JDK to create a executor service which schedules the running /execution of the test suite periodically unless you shut down the service
Please have a look at the below oracle doc
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
Sample
import static java.util.concurrent.TimeUnit.*;
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() { beeperHandle.cancel(true); }
}, 60 * 60, SECONDS);
}
}

EJB polls periodically concurrent Queue

This is my scenario
i have two singleton EJB. The first one receive some data and writes it in a Queue data structure instantiated by the other EJB.
#Singleton
#Startup
public class Client implements IClient {
#EJB
IClientInQueue reporter;
....
#Asynchronous
public void update(String message){
StatusMessage m = new StatusMessage();
reporter.addStatusMessage(m);
}
#Startup
#Singleton
public class ClientInQueue implements IClientInQueue {
private ConcurrentLinkedQueue<StatusMessage> statusInQueue;
addStatusMessage(String m) ..add element to queue
This works fine. Now i want to poll periodically this queue and then make some dispatching operation.
My issue is that a i can't use runnable in ejb context. I'm looking to migrate to spring, but first of make this i want to know if i'm missing something.
thanks
... now I want to poll periodically this queue..
If you need execute some code periodically, the Java EE specification provides a service called Timer Service that is useful in these cases. This service gives you the posibility to execute your code at a defined interval time.
My issue is that a i can't use runnable in ejb context.
Since Java EE 7 (JSR 236: Concurrency Utilities), exists the possibility to create a managed thread, which allows you run new threads within a Container in a safe way.

Why is azure storage queue access so slow when unit testing?

I ran into some difficulty trying to use unit testing with live Azure Storage Queues, and kept writing simpler and simpler examples to try and isolate the problem. In a nutshell, here is what seems to be happening:
Queue access is clearly (and appropriately) lazy-loaded. In my MVC app though, when I get to REALLY need to access the queue (in my case when I call the CloudQueue.Exists method) it is pretty fast. Less than one tenth of a second. However, the VERY same code, when run in the context of a unit test takes about 25 seconds.
I don't understand why there should be this difference, so I made a simple console app that writes something and then reads it from an Azure queue. The console app also takes 25 seconds the first time it is run -- on subsequent runs it takes about 2.5 seconds.
And now for the really weird behavior. I created a Visual Studio 2012 solution with three projects -- one MVC app, one Console app, and one Unit Test project. All three call the same static method which checks for the existence of a queue, creates it if it doesn't exist, writes some data to it and reads some data from it. I have put a timer on the call to CloudQueue.Exists in that method. And here is the deal. When the method is called from the MVC app, the CloudQueue.Exists method consistently completes in about one tenth of a second, whether or not the queue actually does exist. When the method is called from the console app, the first time it is called it takes 25 seconds, and subsequent times it takes about 2.5 seconds. When the method is called from the Unit Test, it consistently takes 25 seconds.
More info: It so happens that when I create this dummy solution, I happened to put my static method (QueueTest) in the console app. Here is what is weird -- if I set the default startup project in Visual Studio to the Console App, then the Unit Test suddenly takes 2.5 seconds. But if I set the startup project in Visual Studio to the MVC app (or to the Unit Test project) then the Unit test takes 25 seconds!
So.... does anyone have a theory of what is going on here? I am baffled.
Code follows below:
Console App:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(QueueTest("my-console-queue", "Console Test"));
}
public static string QueueTest(string queueName, string message)
{
string connectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
CloudQueue queue = queueClient.GetQueueReference(queueName);
DateTime beforeTime = DateTime.Now;
bool doesExist = queue.Exists();
DateTime afterTime = DateTime.Now;
TimeSpan ts = afterTime - beforeTime;
if (!doesExist)
{
queue.Create();
}
CloudQueueMessage qAddMessage = new CloudQueueMessage(message);
queue.AddMessage(qAddMessage);
CloudQueueMessage qGetmessage = queue.GetMessage();
string response = String.Format("{0} ({1} seconds)", qGetmessage.AsString, ts.TotalSeconds);
return response;
}
}
MVC App (Home Controller):
public class HomeController : Controller
{
public ActionResult Index()
{
return Content(Program.QueueTest("my-mvc-queue", "Mvc Test"));
}
}
Unit Test Method: (Note, currently expected to fail!)
[TestClass]
public class QueueUnitTests
{
[TestMethod]
public void CanWriteToAndReadFromQueue()
{
//Arrange
string qName = "my-unit-queue";
string message = "test message";
//Act
string result = Program.QueueTest(qName, message);
//Assert
Assert.IsTrue(String.CompareOrdinal(result,message)==0);
}
}
Of course insight is greatly appreciated.
I suspect this has nothing to do with Azure queues, but rather with .NET trying to determine your proxy settings. What happens if you make some other random System.Net call instead of the call to queue storage?
Try this line of code at the beginning of your app:
System.Net.WebRequest.DefaultWebProxy = null;

Unit testing with timeouts

I am unit testing a class with a property whose value changes often, depending on communication it receives from another component. If the class does not receive any communication for 5 seconds, the property reverts to a default value.
It is easy for me to stub and mock out the communicating component in order to trigger the values I want to test for. The problem is that if I run my unit tests on a machine which is busy (like a build machine), and there is a significant-enough delay to cause the property to default, then my unit test will fail.
How would you test to be sure that this property has the proper value when simulating various communication conditions?
One idea is to restructure my code so that I can stub the part of the class which controls the timeout. Another is to write my unit test such that it can detect if it failed due to a timeout and indicates that in the test results.
I'd try a different approach. Game developers often need a way to control the game time, e.g. for fast-forward functionality or to synchronize frame rates. They introduce a Timer object, which reads ticks from either a hardware clock, or from a simulated clock.
In your case, you could provide a controllable timer for your unit tests and a timer which delegates to system time in production mode. That way, you can control the time which passes for your test case and thus how the class-under-test has to react under certain timeout conditions.
Pseudo-code:
public void testTimeout() throws Exception {
MockTimerClock clock = new MockTimerClock();
ClassUnderTest cut = new ClassUnderTest();
cut.setTimerClock(clock);
cut.beginWaitingForCommunication();
assertTrue(cut.hasDefaultValues());
cut.receiveOtherValues();
assertFalse(cut.hasDefaultValues());
clock.tick(5,TimeUnit.SECONDS);
assertTrue(cut.hasDefaultValues());
cut.shutdown();
}
You could make the timeout property configurable, then set it to a high enough value in your unit tests (or low enough, if you want to unit test the reset behaviour).
There is a similar problem when using DateTime.Now.
Ayende described a trick to deal with it that I liked:
public static class SystemTime
{
public static Func<DateTime> Now = () => DateTime.Now;
}
and then in your test :
[Test]
public void Should_calculate_length_of_stay_from_today_when_still_occupied()
{
var startDate = new DateTime(2008, 10, 1);
SystemTime.Now = () => new DateTime(2008, 10, 5);
var occupation = new Occupation { StartDate = startDate };
occupation.LengthOfStay().ShouldEqual(4);
}
Maybe you can use the same kind of trick for your timeout?