blob: 6b82476fe43a740980e1f20d44436f7625a2ea2f [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.timer;
import org.apache.openejb.BeanContext;
import org.apache.openejb.MethodContext;
import org.apache.openejb.core.timer.CalendarTimerData;
import org.apache.openejb.core.timer.EjbTimeoutJob;
import org.apache.openejb.core.timer.EjbTimerService;
import org.apache.openejb.core.timer.EjbTimerServiceImpl;
import org.apache.openejb.core.timer.ScheduleData;
import org.apache.openejb.core.timer.TimerData;
import org.apache.openejb.jee.Empty;
import org.apache.openejb.jee.StatelessBean;
import org.apache.openejb.junit.ApplicationComposer;
import org.apache.openejb.testing.Module;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.spi.ContainerSystem;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.quartz.JobDataMap;
import org.quartz.impl.triggers.AbstractTrigger;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(ApplicationComposer.class)
public class EjbTimerImplSerializableTest {
@Test
public void serializeDeserialize() throws Exception {
final EjbTimerService timer = timerService();
assertNotNull(timer);
assertThat(timer, instanceOf(EjbTimerServiceImpl.class));
final byte[] serial = serialize(timer);
final EjbTimerService timerDeserialized = (EjbTimerService) deserialize(serial);
assertThat(timerDeserialized, instanceOf(EjbTimerServiceImpl.class));
assertThat(((EjbTimerServiceImpl) timerDeserialized).getScheduler(), notNullValue());
assertEqualsByReflection(timer, timerDeserialized, "deployment");
assertEqualsByReflection(timer, timerDeserialized, "transacted");
assertEqualsByReflection(timer, timerDeserialized, "retryAttempts");
}
@Test
public void serializationOfCalendarData() throws Exception {
final CalendarTimerData data = timerData();
final byte[] serial = serialize(data);
final CalendarTimerData dataDeserialized = (CalendarTimerData) deserialize(serial);
assertThat(dataDeserialized, instanceOf(CalendarTimerData.class));
assertEqualsByReflection(data, dataDeserialized, "id");
assertEqualsByReflection(data, dataDeserialized, "deploymentId");
assertEqualsByReflection(data, dataDeserialized, "timeoutMethod");
assertEqualsByReflection(data, dataDeserialized, "info");
}
@Test
public void jobDataMapSerial() throws Exception {
final CalendarTimerData data = timerData();
final EjbTimerServiceImpl timerService = (EjbTimerServiceImpl) timerService();
data.setScheduler(timerService.getScheduler());
// small hack for the test
final Field preventSynch = TimerData.class.getDeclaredField("synchronizationRegistered");
preventSynch.setAccessible(true);
preventSynch.set(data, true);
data.newTimer();
final AbstractTrigger<?> trigger = (AbstractTrigger<?>) data.getTrigger();
trigger.setJobName("my-job");
trigger.setJobGroup("my-group");
final JobDataMap triggerDataMap = trigger.getJobDataMap();
triggerDataMap.put(EjbTimeoutJob.EJB_TIMERS_SERVICE, timerService);
triggerDataMap.put(EjbTimeoutJob.TIMER_DATA, data);
final byte[] serial = serialize(triggerDataMap);
final JobDataMap map = (JobDataMap) deserialize(serial);
assertTrue(map.containsKey(EjbTimeoutJob.EJB_TIMERS_SERVICE));
assertTrue(map.containsKey(EjbTimeoutJob.TIMER_DATA));
}
private static Object deserialize(final byte[] serial) throws Exception {
final ByteArrayInputStream bais = new ByteArrayInputStream(serial);
final ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
private static byte[] serialize(final Object data) throws Exception {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(data);
return baos.toByteArray();
}
private static void assertEqualsByReflection(final Object o1, final Object o2, final String name) throws Exception {
Class<?> clazz = o1.getClass();
Field field = null;
while (!Object.class.equals(clazz) && clazz.getSuperclass() != null && field == null) {
try {
field = clazz.getDeclaredField(name);
field.setAccessible(true);
} catch (NoSuchFieldException ignored) {
// no-op
}
clazz = clazz.getSuperclass();
}
if (field == null) {
fail();
}
final Object v1 = field.get(o1);
final Object v2 = field.get(o2);
assertEquals(name, v1, v2);
}
private static EjbTimerService timerService() {
final BeanContext context = SystemInstance.get().getComponent(ContainerSystem.class).getBeanContext("EJBWithTimer");
return context.getEjbTimerService();
}
public static CalendarTimerData timerData() throws Exception {
final BeanContext context = SystemInstance.get().getComponent(ContainerSystem.class).getBeanContext("EJBWithTimer");
final EjbTimerService timer = context.getEjbTimerService();
final MethodContext ctx = context.getMethodContext(EJBWithTimer.class.getMethod("doSthg"));
final ScheduleData sd = ctx.getSchedules().iterator().next();
return new CalendarTimerData(1, (EjbTimerServiceImpl) timer, context.getDeploymentID().toString(), null, ctx.getBeanMethod(), sd.getConfig(), sd.getExpression());
}
@Module
public StatelessBean bean() {
final StatelessBean bean = new StatelessBean(EJBWithTimer.class);
bean.setLocalBean(new Empty());
return bean;
}
@Stateless
public static class EJBWithTimer {
// no need to run it, we just want a timer
@Schedule
public void doSthg() {
// no-op
}
}
}