You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ie...@apache.org on 2016/07/27 12:10:14 UTC

svn commit: r1754255 [3/5] - in /sling/trunk/contrib: commons/mom/ commons/mom/api/ commons/mom/api/src/ commons/mom/api/src/main/ commons/mom/api/src/main/java/ commons/mom/api/src/main/java/org/ commons/mom/api/src/main/java/org/apache/ commons/mom/a...

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobImplTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobImplTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobImplTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,388 @@
+/*
+ * 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.sling.jobs.impl;
+
+import org.apache.sling.jobs.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 06/04/2016.
+ */
+public class JobImplTest {
+
+    private Job job;
+    private String jobId;
+    @Mock
+    private JobController jobController;
+    private final long before = System.currentTimeMillis();
+    private long after = System.currentTimeMillis();
+    private boolean jobAborted;
+    private boolean jobStopped;
+
+    public JobImplTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                jobAborted = true;
+                return null;
+            }
+        }).when(jobController).abort();
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                jobStopped = true;
+                return null;
+            }
+        }).when(jobController).stop();
+
+        Thread.sleep(1);
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("job.name", "Jobname");
+        jobId = Utils.generateId();
+        job = new JobImpl(Types.jobQueue("testtopic"), jobId, Types.jobType("testtype"), properties);
+        Thread.sleep(1);
+        after = System.currentTimeMillis();
+
+
+
+    }
+
+
+    @Test
+    public void testGetTopic() throws Exception {
+        assertEquals(Types.jobQueue("testtopic"), job.getQueue());
+    }
+
+    @Test
+    public void testGetId() throws Exception {
+        assertEquals(jobId, job.getId());
+    }
+
+    @Test
+    public void testGetProperties() throws Exception {
+        assertEquals(1, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+    }
+
+    @Test
+    public void testGetRetryCount() throws Exception {
+        assertEquals(0,job.getRetryCount());
+    }
+
+    @Test
+    public void testGetNumberOfRetries() throws Exception {
+        assertEquals(0,job.getNumberOfRetries());
+
+    }
+
+    @Test
+    public void testGetStarted() throws Exception {
+        assertEquals(0, job.getStarted());
+
+    }
+
+    @Test
+    public void testGetCreated() throws Exception {
+        long created = job.getCreated();
+        assertTrue(created > before && created < after);
+
+    }
+
+    @Test
+    public void testGetJobState() throws Exception {
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+
+    }
+
+    @Test
+    public void testSetState() throws Exception {
+        assertEquals(Job.JobState.CREATED,job.getJobState());
+        job.setState(Job.JobState.STOPPED);
+        assertEquals(Job.JobState.STOPPED, job.getJobState());
+
+    }
+
+    @Test
+    public void testGetFinished() throws Exception {
+        assertEquals(0,job.getFinished());
+
+    }
+
+    @Test
+    public void testGetResultMessage() throws Exception {
+        assertEquals("",job.getResultMessage());
+
+    }
+
+    @Test
+    public void testGetController() throws Exception {
+        assertEquals(null,job.getController());
+
+    }
+
+    @Test
+    public void testSetJobController() throws Exception {
+        assertEquals(null,job.getController());
+        job.setJobController(jobController);
+        assertEquals(jobController,job.getController());
+
+    }
+
+    @Test
+    public void testRemoveJobController() throws Exception {
+        assertEquals(null,job.getController());
+        job.setJobController(jobController);
+        assertEquals(jobController, job.getController());
+        job.removeJobController();
+        assertEquals(null, job.getController());
+
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        JobImpl jobImpl = (JobImpl) job;
+        JobUpdateBuilder jobUpdateBuilder = jobImpl.newJobUpdateBuilder();
+        assertNotNull(jobUpdateBuilder);
+        Map<String,Object> updateProperties = new HashMap<String, Object>();
+        updateProperties.put("updateprop", "updatevalue");
+        JobUpdate jobUpdate = jobUpdateBuilder
+                .command(JobUpdate.JobUpdateCommand.START_JOB)
+                .putAll(updateProperties)
+                .put("extra", "extravalue")
+                .build();
+
+        jobImpl.update(jobUpdate);
+
+        // Job update does not change the job state even if the command says so.
+        // the state change comes from a job starter.
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(3, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("extravalue", job.getProperties().get("extra"));
+        assertEquals("updatevalue", job.getProperties().get("updateprop"));
+
+        JobImpl jobImp = new JobImpl(jobUpdate);
+        assertEquals(job.getId(), jobImp.getId());
+
+
+        // update with some, but not all the new properties.
+        updateProperties = new HashMap<String, Object>();
+        updateProperties.put("updateprop", "updatevalue2");
+
+
+        jobImpl.update(jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.UPDATE_JOB)
+                .putAll(updateProperties)
+                .put("extra", "extravalue")
+                .build());
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(3, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("extravalue", job.getProperties().get("extra"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+
+        // remove a property.
+        jobImpl.update(jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.UPDATE_JOB)
+                .put("extra", JobUpdate.JobPropertyAction.REMOVE)
+                .build());
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(2, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+
+        // remove a property.
+        JobUpdate retryUpdate = jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.RETRY_JOB)
+                .put("updateprop", "updatevalue2")
+                .build();
+        set(retryUpdate, "numberOfRetries", 10);
+        set(retryUpdate, "retryCount", 10);
+        jobImpl.update(retryUpdate);
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(2, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+        assertEquals(20, job.getNumberOfRetries());
+        assertEquals(10,job.getRetryCount());
+
+
+
+        // Abort the job without a controller present.
+        jobAborted = false;
+        jobStopped = false;
+        jobImpl.update(jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.ABORT_JOB)
+                .put("extra2", "newextra2")
+                .build());
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(2, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+        assertFalse(jobAborted);
+        assertFalse(jobStopped);
+
+        // set a controller as if the job was stated.
+        job.setJobController(jobController);
+        jobAborted = false;
+        jobStopped = false;
+
+        // abort the job
+        jobImpl.update(jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.ABORT_JOB)
+                .put("extra2", "newextra3")
+                .build());
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        // abort does not update properties.
+        assertEquals(2, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+        assertTrue(jobAborted);
+        assertFalse(jobStopped);
+
+        jobAborted = false;
+        jobStopped = false;
+
+        JobUpdate wrongOrder = jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.UPDATE_JOB)
+                .put("extra2", "newextra4")
+                .build();
+
+        Thread.sleep(2);
+        // abort the job
+        jobImpl.update(jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.STOP_JOB)
+                .put("extra2", "newextra4")
+                .build());
+
+        assertEquals(Job.JobState.CREATED, job.getJobState());
+        assertEquals(2, job.getProperties().size());
+        assertEquals("Jobname", job.getProperties().get("job.name"));
+        assertEquals("updatevalue2", job.getProperties().get("updateprop"));
+        assertFalse(jobAborted);
+        assertTrue(jobStopped);
+
+
+        try {
+            jobImpl.update(wrongOrder);
+            fail("Update should have been rejected due to out of sequence");
+        } catch ( IllegalStateException e) {
+            // ok
+        }
+
+        JobUpdate wrongId = new JobUpdateImpl(Utils.generateId(), JobUpdate.JobUpdateCommand.UPDATE_JOB);
+        try {
+            jobImpl.update(wrongId);
+            fail("Update should have been rejected due wrong Id");
+        } catch ( IllegalArgumentException e) {
+            // ok
+        }
+
+        JobUpdate expired = jobImpl.newJobUpdateBuilder()
+                .command(JobUpdate.JobUpdateCommand.STOP_JOB)
+                .put("extra2", "newextra4")
+                .build();
+        set(expired, "expires", System.currentTimeMillis());
+        Thread.sleep(1);
+        try {
+            jobImpl.update(expired);
+            fail("Update should have expired");
+        } catch ( IllegalStateException e) {
+            // ok
+        }
+
+        try {
+            JobUpdate failJobUpdate = new JobUpdateBuilderImpl(job.getId()).command(JobUpdate.JobUpdateCommand.START_JOB).build();
+            fail("should not be able to build a job by ID only");
+        } catch ( IllegalStateException e) {
+            // ok
+            JobUpdate stopJob = new JobUpdateBuilderImpl(job.getId()).command(JobUpdate.JobUpdateCommand.STOP_JOB).build();
+            JobUpdate abortJob = new JobUpdateBuilderImpl(job.getId()).command(JobUpdate.JobUpdateCommand.ABORT_JOB).build();
+        }
+
+
+    }
+
+    private void set(Object obj, String name, Object v) throws NoSuchFieldException, IllegalAccessException {
+        Field f = obj.getClass().getDeclaredField(name);
+        f.setAccessible(true);
+        f.set(obj, v);
+    }
+
+
+    @Test
+    public  void testNewJobUpdateBuilder() throws Exception {
+        long updateBefore = System.currentTimeMillis();
+        Thread.sleep(1);
+
+        JobImpl jobImpl = (JobImpl) job;
+        JobUpdateBuilder jobUpdateBuilder = jobImpl.newJobUpdateBuilder();
+        assertNotNull(jobUpdateBuilder);
+        Map<String,Object> updateProperties = new HashMap<String, Object>();
+        updateProperties.put("updateprop", "updatevalue");
+        JobUpdate jobUpdate = jobUpdateBuilder
+                .command(JobUpdate.JobUpdateCommand.START_JOB)
+                .putAll(updateProperties)
+                .put("extra", "extravalue")
+                .build();
+
+
+        Thread.sleep(1);
+        long updateAfter = System.currentTimeMillis();
+        assertNotNull(jobUpdate);
+        assertEquals(jobId, jobUpdate.getId());
+        assertEquals(Types.jobQueue("testtopic"), jobUpdate.getQueue());
+        assertEquals("", jobUpdate.getResultMessage());
+        assertTrue(jobUpdate.expires() > updateAfter);
+        assertTrue(jobUpdate.updateTimestamp() > updateBefore && jobUpdate.updateTimestamp() < updateAfter);
+        assertTrue(jobUpdate.getCreated() > before && jobUpdate.getCreated() < after);
+        assertEquals(JobUpdate.JobUpdateCommand.START_JOB, jobUpdate.getCommand());
+        assertEquals(Job.JobState.CREATED, jobUpdate.getState());
+        assertEquals(0, jobUpdate.getStarted());
+        assertEquals(0,jobUpdate.getFinished());
+        assertEquals(0,jobUpdate.getRetryCount());
+        assertEquals(0,jobUpdate.getNumberOfRetries());
+        assertEquals(2,jobUpdate.getProperties().size());
+        assertEquals("extravalue", jobUpdate.getProperties().get("extra"));
+        assertEquals("updatevalue",jobUpdate.getProperties().get("updateprop"));
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobManagerImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobManagerImplTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobManagerImplTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobManagerImplTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,297 @@
+/*
+ * 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.sling.jobs.impl;
+
+import org.apache.sling.jobs.*;
+import org.apache.sling.jobs.Types;
+import org.apache.sling.jobs.impl.spi.JobStorage;
+import org.apache.sling.jobs.impl.storage.InMemoryJobStorage;
+import org.apache.sling.mom.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 06/04/2016.
+ */
+public class JobManagerImplTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JobManagerImplTest.class);
+    private JobManager jobManager;
+    private JobStorage jobStorage;
+    private OutboundJobUpdateListener messageSender;
+    @Mock
+    private TopicManager topicManager;
+    @Mock
+    private QueueManager queueManager;
+    private Map<org.apache.sling.mom.Types.TopicName, Queue<QueueEntry>> topicQueues;
+    private Map<org.apache.sling.mom.Types.QueueName, Queue<QueueEntry>> messageQueues;
+
+    public JobManagerImplTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        topicQueues = new HashMap<org.apache.sling.mom.Types.TopicName, Queue<QueueEntry>>();
+        messageQueues = new HashMap<org.apache.sling.mom.Types.QueueName, Queue<QueueEntry>>();
+        //noinspection unchecked
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                org.apache.sling.mom.Types.TopicName topic = (org.apache.sling.mom.Types.TopicName) invocationOnMock.getArguments()[0];
+                org.apache.sling.mom.Types.CommandName command = (org.apache.sling.mom.Types.CommandName) invocationOnMock.getArguments()[1];
+                @SuppressWarnings("unchecked") Map<String, Object> properties = (Map<String, Object>) invocationOnMock.getArguments()[2];
+                LOGGER.info("Topic Manager publish {} {} {} ", new Object[]{ topic, command, properties });
+                Queue<QueueEntry> queue = topicQueues.get(topic);
+                if ( queue == null) {
+                    queue = new ArrayBlockingQueue<QueueEntry>(100);
+                    topicQueues.put(topic, queue);
+
+                }
+                queue.add(new QueueEntry(command, properties));
+                return null;
+            }
+        }).when(topicManager)
+                .publish(Mockito.any(org.apache.sling.mom.Types.TopicName.class), Mockito.any(org.apache.sling.mom.Types.CommandName.class), Mockito.any(Map.class));
+
+        //noinspection unchecked
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                org.apache.sling.mom.Types.QueueName topic = (org.apache.sling.mom.Types.QueueName) invocationOnMock.getArguments()[0];
+                @SuppressWarnings("unchecked") Map<String, Object> properties = (Map<String, Object>) invocationOnMock.getArguments()[1];
+                LOGGER.info("Queue Manager add {} {} {} ", new Object[]{ topic, properties });
+                Queue<QueueEntry> queue = messageQueues.get(topic);
+                if ( queue == null) {
+                    queue = new ArrayBlockingQueue<QueueEntry>(100);
+                    messageQueues.put(topic, queue);
+
+                }
+                queue.add(new QueueEntry(properties));
+                return null;
+            }
+        }).when(queueManager)
+                .add(Mockito.any(org.apache.sling.mom.Types.QueueName.class), Mockito.any(Map.class));
+
+        messageSender = new OutboundJobUpdateListener(topicManager, queueManager);
+        jobStorage = new InMemoryJobStorage();
+        jobManager = new JobManagerImpl(jobStorage, messageSender);
+
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        messageSender.dispose();
+        jobStorage.dispose();
+    }
+
+    @Test
+    public void testCreateJob() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+
+        assertEquals(testId, job.getProperties().get("testid"));
+        org.apache.sling.mom.Types.TopicName topicName = org.apache.sling.mom.Types.topicName("testtopic");
+        assertNotNull(messageQueues.get(topicName));
+        assertEquals(1, messageQueues.get(topicName).size());
+        QueueEntry qe = messageQueues.get(topicName).remove();
+        assertNotNull(qe);
+        Map<String, Object> jobProperties = qe.getProperties();
+
+        // pretend to consume the job message
+        JobImpl dequeuedJob = new JobImpl(new JobUpdateImpl(jobProperties));
+        assertEquals(job.getId(), dequeuedJob.getId());
+        // the operation of the job object is tested in other unit tests, don't repeat that here.
+        assertEquals(testId, dequeuedJob.getProperties().get("testid"));
+
+    }
+
+    @Test
+    public void testGetJobById() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+
+
+        Job searchedJob = jobManager.getJobById(job.getId());
+        assertNotNull(searchedJob);
+        assertEquals(job.getId(), searchedJob.getId());
+        assertEquals(testId, searchedJob.getProperties().get("testid"));
+
+    }
+
+    private Job createJob(String testId) {
+        Map<String, Object> testProps = new HashMap<String, Object>();
+        testProps.put("job.name", "Jobname ");
+        testProps.put("testid", testId);
+        Job job = jobManager.newJobBuilder(Types.jobQueue("testtopic"), Types.jobType("testtype"))
+                .addProperties(testProps)
+                .add();
+        assertNotNull(job);
+        return job;
+    }
+
+    @Test
+    public void testGetJob() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+        Map<String, Object> template = new HashMap<String, Object>();
+        template.put("testid", testId);
+        try {
+            Job searchedJob = jobManager.getJob(job.getQueue(), template);
+            assertNotNull(searchedJob);
+            assertEquals(job.getId(), searchedJob.getId());
+            assertEquals(testId, searchedJob.getProperties().get("testid"));
+        } catch ( UnsupportedOperationException e) {
+            LOGGER.info("Method getJob to be implemented. Cant be tested, so test passes for the moment.");
+        }
+
+    }
+
+    @Test
+    public void testFindJobs() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+        Map<String, Object> template = new HashMap<String, Object>();
+        template.put("testid", testId);
+        try {
+            @SuppressWarnings("unchecked") Collection<Job> searchedResults = jobManager.findJobs(JobManager.QueryType.ALL, job.getQueue(), 10, template);
+            assertNotNull(searchedResults);
+            fail("Implement code to test search results");
+        } catch ( UnsupportedOperationException e) {
+            LOGGER.info("Method findJobs to be implemented. Cant be tested, so test passes for the moment.");
+        }
+
+    }
+
+    @Test
+    public void testStopJobById() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+        Thread.sleep(10);
+        jobManager.stopJobById(job.getId());
+        Queue<QueueEntry> messageQ = messageQueues.get(org.apache.sling.mom.Types.queueName("testtopic"));
+        Queue<QueueEntry> topicQ = topicQueues.get(org.apache.sling.mom.Types.topicName("testtopic"));
+        assertEquals(1,messageQ.size());
+        QueueEntry qe = messageQ.remove();
+        assertNotNull(qe);
+        Map<String, Object> jobProperties = qe.getProperties();
+
+        // get the job off the queue.
+        JobImpl dequeuedJob = new JobImpl(new JobUpdateImpl(jobProperties));
+        assertEquals(job.getId(), dequeuedJob.getId());
+        // the operation of the job object is tested in other unit tests, don't repeat that here.
+        assertEquals(testId, dequeuedJob.getProperties().get("testid"));
+
+
+        // get any messages sent to the topic.
+        assertEquals(1, topicQ.size());
+        QueueEntry stoppedQE = topicQ.remove();
+        Map<String, Object> stoppedJobProperties = stoppedQE.getProperties();
+        assertNotNull(stoppedJobProperties);
+        JobImpl stoppedJob = new JobImpl(new JobUpdateImpl(stoppedJobProperties));
+        assertEquals(JobUpdate.JobUpdateCommand.STOP_JOB.asCommandName(), stoppedQE.getCommand());
+        assertEquals(job.getId(), stoppedJob.getId());
+        // the stop message to the topic wont have any properties.
+
+
+
+    }
+
+    @Test
+    public void testAbortJob() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+        Thread.sleep(10);
+        jobManager.abortJob(job.getId());
+        LOGGER.info("Message Queues  {}", messageQueues);
+        LOGGER.info("Topic Queues  {}", topicQueues);
+        Queue<QueueEntry> messageQ = messageQueues.get(org.apache.sling.mom.Types.queueName("testtopic"));
+        Queue<QueueEntry> topicQ = topicQueues.get(org.apache.sling.mom.Types.topicName("testtopic"));
+        assertEquals(1,messageQ.size());
+        QueueEntry qe = messageQ.remove();
+        assertNotNull(qe);
+        Map<String, Object> jobProperties = qe.getProperties();
+
+        // get the job off the queue.
+        JobImpl dequeuedJob = new JobImpl(new JobUpdateImpl(jobProperties));
+        assertEquals(job.getId(), dequeuedJob.getId());
+        // the operation of the job object is tested in other unit tests, dont repeat that here.
+        assertEquals(testId, dequeuedJob.getProperties().get("testid"));
+
+
+        // get any messages sent to the topic.
+        assertEquals(1, topicQ.size());
+        QueueEntry stoppedQE = topicQ.remove();
+        Map<String, Object> stoppedJobProperties = stoppedQE.getProperties();
+        assertNotNull(stoppedJobProperties);
+        JobImpl stoppedJob = new JobImpl(new JobUpdateImpl(stoppedJobProperties));
+        assertEquals(JobUpdate.JobUpdateCommand.ABORT_JOB.asCommandName(), stoppedQE.getCommand());
+        assertEquals(job.getId(), stoppedJob.getId());
+
+    }
+
+    @Test
+    public void testRetryJobById() throws Exception {
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        Job job = createJob(testId);
+        Thread.sleep(10);
+        jobManager.retryJobById(job.getId());
+        Queue<QueueEntry> messageQ = messageQueues.get(org.apache.sling.mom.Types.queueName("testtopic"));
+        Queue<QueueEntry> topicQ = topicQueues.get(org.apache.sling.mom.Types.topicName("testtopic"));
+        assertEquals(1,messageQ.size());
+        QueueEntry qe = messageQ.remove();
+        assertNotNull(qe);
+        Map<String, Object> jobProperties = qe.getProperties();
+
+        // get the job off the queue.
+        JobImpl dequeuedJob = new JobImpl(new JobUpdateImpl(jobProperties));
+        assertEquals(job.getId(), dequeuedJob.getId());
+        // the operation of the job object is tested in other unit tests, don't repeat that here.
+        assertEquals(testId, dequeuedJob.getProperties().get("testid"));
+
+
+        // get any messages sent to the topic.
+        assertEquals(1, topicQ.size());
+        QueueEntry stoppedQE = topicQ.remove();
+        Map<String, Object> stoppedJobProperties = stoppedQE.getProperties();
+        assertNotNull(stoppedJobProperties);
+        JobImpl stoppedJob = new JobImpl(new JobUpdateImpl(stoppedJobProperties));
+        assertEquals(JobUpdate.JobUpdateCommand.RETRY_JOB.asCommandName(), stoppedQE.getCommand());
+        assertEquals(job.getId(), stoppedJob.getId());
+
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobManagerImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobUpdateImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobUpdateImplTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobUpdateImplTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobUpdateImplTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,82 @@
+/*
+ * 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.sling.jobs.impl;
+
+import org.apache.sling.jobs.Job;
+import org.apache.sling.jobs.JobUpdate;
+import org.apache.sling.jobs.Types;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 06/04/2016.
+ */
+public class JobUpdateImplTest {
+
+    private String jobId;
+    private JobImpl job;
+
+    @Before
+    public void setUp() throws Exception {
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("job.name", "Jobname");
+        jobId = Utils.generateId();
+        job = new JobImpl(Types.jobQueue("testtopic"), jobId, Types.jobType("testtype"), properties);
+    }
+
+    @Test
+    public void test() throws Exception {
+
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("Update", "update value");
+        JobUpdateImpl jobUpdate = new JobUpdateImpl(job, JobUpdate.JobUpdateCommand.START_JOB, properties);
+
+        Map<String, Object> value = Utils.toMapValue(jobUpdate);
+        assertNotNull(value);
+        System.err.println("Value is " + value);
+        assertEquals(14, value.size());
+
+        JobUpdate jobUpdateCopy = new JobUpdateImpl(value);
+        assertEquals(jobUpdate.getId(), jobUpdateCopy.getId());
+        assertEquals(jobUpdate.expires(), jobUpdateCopy.expires());
+        assertEquals(jobUpdate.updateTimestamp(), jobUpdateCopy.updateTimestamp());
+        assertEquals(jobUpdate.getCreated(), jobUpdateCopy.getCreated());
+        assertEquals(jobUpdate.getStarted(), jobUpdateCopy.getStarted());
+        assertEquals(jobUpdate.getCommand(), jobUpdateCopy.getCommand());
+        assertEquals(jobUpdate.getFinished(), jobUpdateCopy.getFinished());
+        assertEquals(jobUpdate.getResultMessage(), jobUpdateCopy.getResultMessage());
+        assertEquals(jobUpdate.getNumberOfRetries(), jobUpdateCopy.getNumberOfRetries());
+        assertEquals(jobUpdate.getRetryCount(), jobUpdateCopy.getRetryCount());
+        assertEquals(jobUpdate.getState(), jobUpdateCopy.getState());
+        assertEquals(jobUpdate.getQueue(), jobUpdateCopy.getQueue());
+        Map<String, Object> originalProperties = jobUpdate.getProperties();
+        Map<String, Object> copyProperties = jobUpdateCopy.getProperties();
+        assertEquals(1, copyProperties.size());
+        assertEquals(copyProperties.size(), copyProperties.size());
+        assertEquals("update value", originalProperties.get("Update"));
+        assertEquals(originalProperties.get("Update"), copyProperties.get("Update"));
+
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/JobUpdateImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/ManagerSubscriberTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/ManagerSubscriberTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/ManagerSubscriberTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/ManagerSubscriberTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,151 @@
+/*
+ * 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.sling.jobs.impl;
+
+import aQute.libg.command.Command;
+import org.apache.sling.jobs.Job;
+import org.apache.sling.jobs.JobUpdate;
+import org.apache.sling.jobs.Types;
+import org.apache.sling.jobs.impl.spi.JobStorage;
+import org.apache.sling.jobs.impl.storage.InMemoryJobStorage;
+import org.apache.sling.mom.QueueManager;
+import org.apache.sling.mom.TopicManager;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 07/04/2016.
+ */
+public class ManagerSubscriberTest {
+
+    private JobManagerImpl jobManager;
+    private JobStorage jobStorage;
+    private OutboundJobUpdateListener messageSender;
+    @Mock
+    private TopicManager topicManager;
+    @Mock
+    private QueueManager queueManager;
+    private HashMap<org.apache.sling.mom.Types.TopicName, Queue<QueueEntry>> topicQueues;
+    private HashMap<org.apache.sling.mom.Types.QueueName, Queue<QueueEntry>> messageQueues;
+    private ManagerSubscriber managerSubscriber;
+
+    public ManagerSubscriberTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        topicQueues = new HashMap<org.apache.sling.mom.Types.TopicName, Queue<QueueEntry>>();
+        messageQueues = new HashMap<org.apache.sling.mom.Types.QueueName, Queue<QueueEntry>>();
+        //noinspection unchecked
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                org.apache.sling.mom.Types.TopicName topic = (org.apache.sling.mom.Types.TopicName) invocationOnMock.getArguments()[0];
+                org.apache.sling.mom.Types.CommandName command = (org.apache.sling.mom.Types.CommandName) invocationOnMock.getArguments()[1];
+                @SuppressWarnings("unchecked") Map<String, Object> properties = (Map<String, Object>) invocationOnMock.getArguments()[2];
+                Queue<QueueEntry> queue = topicQueues.get(topic);
+                if (queue == null) {
+                    queue = new ArrayBlockingQueue<QueueEntry>(100);
+                    topicQueues.put(topic, queue);
+
+                }
+                queue.add(new QueueEntry(command, properties));
+                return null;
+            }
+        }).when(topicManager)
+                .publish(Mockito.any(org.apache.sling.mom.Types.TopicName.class), Mockito.any(org.apache.sling.mom.Types.CommandName.class), Mockito.any(Map.class));
+
+        //noinspection unchecked
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                org.apache.sling.mom.Types.QueueName topic = (org.apache.sling.mom.Types.QueueName) invocationOnMock.getArguments()[0];
+                @SuppressWarnings("unchecked") Map<String, Object> properties = (Map<String, Object>) invocationOnMock.getArguments()[1];
+                Queue<QueueEntry> queue = messageQueues.get(topic);
+                if ( queue == null) {
+                    queue = new ArrayBlockingQueue<QueueEntry>(100);
+                    messageQueues.put(topic, queue);
+
+                }
+                queue.add(new QueueEntry(properties));
+                return null;
+            }
+        }).when(queueManager)
+                .add(Mockito.any(org.apache.sling.mom.Types.QueueName.class), Mockito.any(Map.class));
+
+        messageSender = new OutboundJobUpdateListener(topicManager, queueManager);
+        jobStorage = new InMemoryJobStorage();
+        jobManager = new JobManagerImpl(jobStorage, messageSender);
+
+        managerSubscriber = new ManagerSubscriber();
+        Field f = managerSubscriber.getClass().getDeclaredField("jobManager");
+        f.setAccessible(true);
+        f.set(managerSubscriber,jobManager);
+
+
+    }
+
+    @After
+    public void after() {
+        jobManager.dispose();
+        jobStorage.dispose();
+    }
+
+    @Test
+    public void test() {
+        // fake up a remote send.
+        Map<String, Object> properties = new HashMap<String, Object>();
+        String testId = "testGetJobById"+System.currentTimeMillis();
+        properties.put("testid", testId);
+        properties.put("job.name", "Jobname");
+        String jobId = Utils.generateId();
+        Job job = new JobImpl(Types.jobQueue("testtopic"), jobId,Types.jobType("testtype"), properties);
+        JobUpdateImpl jobUpdate = new JobUpdateImpl(job, JobUpdate.JobUpdateCommand.START_JOB, job.getProperties());
+
+        Map<String, Object> message = Utils.toMapValue(jobUpdate);
+
+        // pump the topic message into the managerSubscriber and check that the job can be found.
+
+        managerSubscriber.onMessage(org.apache.sling.mom.Types.topicName("testtopic"), message);
+
+        Job searchedJob = jobManager.getJobById(jobId);
+        assertNotNull(searchedJob);
+        assertEquals(job.getId(), searchedJob.getId());
+        assertEquals(testId, searchedJob.getProperties().get("testid"));
+
+    }
+
+
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/ManagerSubscriberTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/QueueEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/QueueEntry.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/QueueEntry.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/QueueEntry.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,49 @@
+/*
+ * 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.sling.jobs.impl;
+
+import org.apache.sling.mom.Types;
+
+import java.util.Map;
+
+/**
+ * Created by ieb on 06/04/2016.
+ */
+class QueueEntry {
+    private final Types.CommandName name;
+    private final Map<String, Object> properties;
+
+    public QueueEntry(Types.CommandName name, Map<String, Object> properties) {
+        this.name = name;
+        this.properties = properties;
+    }
+
+    public QueueEntry(Map<String, Object> properties) {
+        this.name = null;
+        this.properties = properties;
+    }
+
+    public Types.CommandName getCommand() {
+        return name;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/QueueEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/UtilsTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/UtilsTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/UtilsTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/UtilsTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,115 @@
+/*
+ * 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.sling.jobs.impl;
+
+import org.apache.sling.jobs.impl.spi.MapValueAdapter;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 05/04/2016.
+ */
+public class UtilsTest {
+
+    @Test
+    public void testGenerateId() throws Exception {
+        // check the IDs don't clash. Cant check between separate JVMs without separate JVMs.
+        Set<String> ids = new HashSet<String>();
+        for ( int i = 0; i < 100; i++ ) {
+            ids.add(Utils.generateId());
+        }
+        assertEquals(100, ids.size());
+
+    }
+
+    @Test
+    public void testToMapValue() throws Exception {
+        final Map<String, Object> testMap = new HashMap<String, Object>();
+        testMap.put("v", "a");
+        Object mv = Utils.toMapValue(testMap);
+        assertEquals(testMap.size(), ((Map)mv).size());
+        assertEquals("a", ((Map)mv).get("v"));
+
+        mv = Utils.toMapValue(new MapValueAdapter() {
+            @Override
+            public void fromMapValue(Object mapValue) {
+
+            }
+
+            @Override
+            public Object toMapValue() {
+                return testMap;
+            }
+        });
+        assertEquals(testMap.size(), ((Map)mv).size());
+        assertEquals("a", ((Map)mv).get("v"));
+
+        try {
+            mv = Utils.toMapValue(new HashSet<String>());
+            fail("Should have rejected a hash set");
+        } catch ( IllegalArgumentException e) {
+            // ok
+        }
+
+        try {
+            mv = Utils.toMapValue(new MapValueAdapter() {
+                @Override
+                public void fromMapValue(Object mapValue) {
+
+                }
+
+                @Override
+                public Object toMapValue() {
+                    return "should not be allowed as a MapValue is supposed to be a Map";
+                }
+            });
+            fail("Should have rejected a string from map Utils.toMapValue even if internal");
+        } catch ( IllegalArgumentException e) {
+            // ok
+        }
+
+    }
+
+    @Test
+    public void testGetRequired() throws Exception {
+        final Map<String, Object> testMap = new HashMap<String, Object>();
+        testMap.put("v", "a");
+        assertEquals("a",Utils.getRequired(testMap, "v"));
+        try {
+            Utils.getRequired(testMap, "z");
+            fail("Expected z to be missing and fail required test");
+        } catch ( IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void testGetOptional() throws Exception {
+        final Map<String, Object> testMap = new HashMap<String, Object>();
+        testMap.put("v", "a");
+        assertEquals("a", Utils.getOptional(testMap, "v", "xx"));
+        assertEquals("xx",Utils.getOptional(testMap, "z", "xx"));
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/UtilsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/storage/InMemoryJobStorageTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/storage/InMemoryJobStorageTest.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/storage/InMemoryJobStorageTest.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/storage/InMemoryJobStorageTest.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,91 @@
+/*
+ * 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.sling.jobs.impl.storage;
+
+import org.apache.sling.jobs.Job;
+import org.apache.sling.jobs.impl.Utils;
+import org.apache.sling.jobs.impl.spi.JobStorage;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 05/04/2016.
+ * Tests in memory storage.
+ */
+public class InMemoryJobStorageTest {
+
+    private JobStorage jobStorage;
+
+    @Mock
+    private Job job;
+    private String jobId;
+
+    public InMemoryJobStorageTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        jobId = Utils.generateId();
+        Mockito.when(job.getId()).thenReturn(jobId);
+        jobStorage = new InMemoryJobStorage();
+        jobStorage.put(job);
+    }
+
+
+    @Test
+    public void testGet() throws Exception {
+        String nextJobId = Utils.generateId();
+        assertEquals(jobId, jobStorage.get(jobId).getId());
+        assertNull(jobStorage.get(nextJobId));
+    }
+
+    @Test
+    public void testPut() throws Exception {
+        String nextJobId = Utils.generateId();
+        Job newJob = Mockito.mock(Job.class);
+        Mockito.when(newJob.getId()).thenReturn(nextJobId);
+        jobStorage.put(newJob);
+
+        assertEquals(jobId, jobStorage.get(jobId).getId());
+        assertEquals(nextJobId, jobStorage.get(nextJobId).getId());
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        Job removed = jobStorage.remove(job);
+        assertNotNull(removed);
+        assertEquals(job.getId(), removed.getId());
+        assertNull(jobStorage.get(jobId));
+    }
+
+    @Test
+    public void testRemove1() throws Exception {
+        Job removed = jobStorage.remove(job.getId());
+        assertNotNull(removed);
+        assertEquals(job.getId(), removed.getId());
+        assertNull(jobStorage.get(jobId));
+
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/core/src/test/java/org/apache/sling/jobs/impl/storage/InMemoryJobStorageTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml Wed Jul 27 12:10:12 2016
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>26</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.jobs-it-services</artifactId>
+    <packaging>bundle</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <name>Apache Sling Jobs Service Integration Tests Bundle</name>
+    <description>
+        Integration tests for the Jobs implementation
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/commons/mom/examples/jobs/it-services</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/commons/mom/examples/jobs/it-services</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services</url>
+    </scm>
+
+    <properties>
+        <site.jira.version.id>12315369</site.jira.version.id>
+        <sling.java.version>7</sling.java.version>
+        <exam.version>4.4.0</exam.version>
+        <url.version>2.4.5</url.version>
+        <bundle.build.dir>${basedir}/target</bundle.build.dir>
+        <bundle.file.name>${bundle.build.dir}/${project.build.finalName}.jar</bundle.file.name>
+        <min.port>37000</min.port>
+        <max.port>37999</max.port>
+    </properties>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>
+                    </excludePackageNames>
+                </configuration>
+            </plugin>
+        </plugins>
+    </reporting>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jobs</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+      <!-- Testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/AsyncJobConsumer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/AsyncJobConsumer.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/AsyncJobConsumer.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/AsyncJobConsumer.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,143 @@
+/*
+ * 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.sling.jobs.it.services;
+
+import org.apache.felix.scr.annotations.*;
+import org.apache.sling.jobs.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.Map;
+import java.util.concurrent.*;
+
+/**
+ * Created by ieb on 15/04/2016.
+ * This job consumer consumes jobs from the job subsystem. It accepts the jobs into a queue and uses a thread pool to drain the queue.
+ * If the queue fills up, jobs are returned back to the jobsystem without being accepted. The size of the queue, the number of threads and
+ * the maximum number of threads should be tuned for maximum throughput at an acceptable resource usage level. Retuning the consumer
+ * will cause the queue to drain and restart.
+ *
+ * The contract this component makes with the JobSystem is that it will make best efforts to ensure that jobs it accepts into its queue are executed.
+ *
+ */
+@Component(immediate = true)
+@Properties({
+        @Property(name = JobConsumer.JOB_TYPES, cardinality = Integer.MAX_VALUE, value = {
+                AsyncJobConsumer.JOB_TYPE
+        })
+})
+@Service(value = JobConsumer.class)
+public class AsyncJobConsumer implements JobConsumer {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncJobConsumer.class);
+
+
+    public static final String JOB_TYPE = "treadding/asyncthreadpoolwithbacklog";
+
+    /**
+     * The core number of threads that can be used to run this job. This should be just large enough to ensure
+     * throughput without being so large as to impact other operations. Probably 1/2 the number of cores is a good
+     * starting point.
+     */
+    @Property(intValue = 4)
+    private static final String CORE_THREAD_POOL_SIZE = "core-thread-pool-size";
+    /**
+     * The maximum number of threads allocated to running this job. This should not be so large that it can
+     * create availability issues for the JVM, but large enough to clear the backlog before it experiences
+     * inefficiency due to overflow.
+     */
+    @Property(intValue = 8)
+    private static final String MAC_THREAD_POOL_SIZE = "max-thread-pool-size";
+
+    /**
+     * This defines how many messages the component can queue for execution dequeing from the
+     * Job queue. This should be just large enough to ensure that the executing threads are kept busy
+     * but small enough to ensure that the shutdown is not blocked. Once into the queue there is some
+     * impression that the jobs will be executed as they have been dequeued from the message system.
+     * The deactivate will wait for the shutdown wait time, and then shut the queue down.
+     */
+    @Property(intValue = 8)
+    private static final String MAX_QUEUED_BACKLOG = "max-queue-backlog";
+
+    /**
+     * This is the maximum time allowed to shut the queue down. It should be long enough to ensure that all jobs in
+     * the local queue can complete. The longer the local queue set in max-queue-backlog, the higher this value must be.
+     */
+    @Property(longValue = 30)
+    private static final String SHUTDOWN_WAIT_SECONDS = "max-shutdown-wait";
+
+    private ExecutorService executor;
+    private LinkedBlockingQueue<Runnable> workQueue;
+    private long shutdownWaitSeconds;
+
+    @Activate
+    public void activate(Map<String, Object> properites) {
+        int corePoolSize = (int) properites.get(CORE_THREAD_POOL_SIZE);
+        int maxPoolSize = (int) properites.get(MAC_THREAD_POOL_SIZE);
+        int maxBacklog = (int) properites.get(MAX_QUEUED_BACKLOG);
+        shutdownWaitSeconds = (long) properites.get(SHUTDOWN_WAIT_SECONDS);
+        workQueue = new LinkedBlockingQueue<Runnable>(maxBacklog);
+        executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, 60, TimeUnit.SECONDS, workQueue);
+    }
+
+    @Deactivate
+    public void deactivate(Map<String, Object> properties) {
+        try {
+            executor.awaitTermination(shutdownWaitSeconds, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("Interrupted while waiting for queue to drain ",e);
+        }
+        executor.shutdown();
+    }
+
+    @Nonnull
+    @Override
+    public void execute(@Nonnull final Job initialState, @Nonnull final JobUpdateListener listener, @Nonnull final JobCallback callback) {
+        LOGGER.info("Got request to start job {} ", initialState);
+        initialState.setState(Job.JobState.QUEUED);
+        listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step1").build());
+        // if the Job cant be queued locally, a RejectedExecutionException will be thrown, back to the scheduler and the job message will be put back into the queue to be retried some time later.
+        executor.submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                initialState.setState(Job.JobState.ACTIVE);
+                listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step1").build());
+                // DO some work here.
+
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    LOGGER.debug(e.getMessage(), e);
+                }
+                listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step2").build());
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    LOGGER.debug(e.getMessage(), e);
+                }
+                initialState.setState(Job.JobState.SUCCEEDED);
+                listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step3").build());
+                callback.callback(initialState);
+                return null;
+            }
+        });
+    }
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/AsyncJobConsumer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/FullySyncJob.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/FullySyncJob.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/FullySyncJob.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/FullySyncJob.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,69 @@
+/*
+ * 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.sling.jobs.it.services;
+
+import org.apache.felix.scr.annotations.*;
+import org.apache.sling.jobs.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Created by ieb on 11/04/2016.
+ */
+@Component(immediate = true)
+@Properties({
+        @Property(name = JobConsumer.JOB_TYPES, cardinality = Integer.MAX_VALUE, value = {
+                FullySyncJob.JOB_TYPE
+        })
+})
+@Service(value = JobConsumer.class)
+public class FullySyncJob implements JobConsumer {
+
+
+    public static final String JOB_TYPE = "treadding/inthreadoperation";
+    private static final Logger LOGGER = LoggerFactory.getLogger(FullySyncJob.class);
+
+    @Nonnull
+    @Override
+    public void execute(@Nonnull Job initialState, @Nonnull JobUpdateListener listener, @Nonnull JobCallback callback) {
+        LOGGER.info("Got request to start job {} ", initialState);
+        initialState.setState(Job.JobState.ACTIVE);
+        listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step1").build());
+
+        // DO some work here.
+
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            LOGGER.debug(e.getMessage(), e);
+        }
+        listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step2").build());
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            LOGGER.debug(e.getMessage(),e);
+        }
+        initialState.setState(Job.JobState.SUCCEEDED);
+        listener.update(initialState.newJobUpdateBuilder().command(JobUpdate.JobUpdateCommand.UPDATE_JOB).put("processing", "step3").build());
+        callback.callback(initialState);
+    }
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/FullySyncJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/JobManagerTestComponent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/JobManagerTestComponent.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/JobManagerTestComponent.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/JobManagerTestComponent.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,73 @@
+/*
+ * 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.sling.jobs.it.services;
+
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.sling.jobs.Job;
+import org.apache.sling.jobs.JobManager;
+import org.apache.sling.jobs.Types;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 11/04/2016.
+ */
+@Component(immediate = true)
+public class JobManagerTestComponent  {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JobManagerTestComponent.class);
+    public static final String TOPIC = "org/apache/sling/jobs/it/services";
+    @Reference
+    private JobManager jobManager;
+
+
+    @Activate
+    public void activate(Map<String,Object> props) {
+        for( int i = 0; i < 10; i++) {
+            Job job = jobManager.newJobBuilder(Types.jobQueue(TOPIC), Types.jobType(AsyncJobConsumer.JOB_TYPE)).addProperties(
+                    ImmutableMap.of("jobtest", (Object) "jobtest")).add();
+            assertNotNull(job);
+            LOGGER.info("Started Job {} ", job.getId());
+        }
+        // then start 10 sync jobs.
+        for( int i = 0; i < 10; i++) {
+            Job job = jobManager.newJobBuilder(Types.jobQueue(TOPIC), Types.jobType(FullySyncJob.JOB_TYPE)).addProperties(
+                    ImmutableMap.of("jobtest", (Object) "jobtest")).add();
+            assertNotNull(job);
+            LOGGER.info("Started Job {} ", job.getId());
+        }
+    }
+
+    @Deactivate
+    public void deactivate(Map<String, Object> props) {
+
+    }
+
+
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/src/main/java/org/apache/sling/jobs/it/services/JobManagerTestComponent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp Wed Jul 27 12:10:12 2016
@@ -0,0 +1,44 @@
+<%--
+/*
+ * 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.
+ */
+--%><%@include file="/libs/foundation/global.jsp"%><%
+%><%@page session="false" contentType="text/html; charset=utf-8"
+	pageEncoding="UTF-8"
+    import="org.apache.sling.api.resource.*,
+    java.util.*,
+    javax.jcr.*,
+    com.day.cq.search.*,
+    com.day.cq.wcm.api.*,
+    com.day.cq.dam.api.*,
+    org.apache.sling.jobs.*,
+    com.google.common.collect.*"%><%
+
+    // This is an AEM Fiddle that runs some jobs.
+
+    JobManager jobManager = sling.getService(JobManager.class);
+    for ( int i = 0; i < 100; i++ ) {
+        Job job = jobManager.newJobBuilder(
+                Types.jobQueue("org/apache/sling/jobs/it/services"),
+                Types.jobType("treadding/asyncthreadpoolwithbacklog"))
+            .addProperties(
+                        ImmutableMap.of("jobtest", (Object) "jobtest"))
+            .add();
+%>Added Job <%= job.getId() %><br/><%
+    }
+%>
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it-services/testlaunch.jsp
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Added: sling/trunk/contrib/commons/mom/examples/jobs/it/.gitignore
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it/.gitignore?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it/.gitignore (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it/.gitignore Wed Jul 27 12:10:12 2016
@@ -0,0 +1 @@
+activemq-data

Added: sling/trunk/contrib/commons/mom/examples/jobs/it/README.md
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it/README.md?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it/README.md (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it/README.md Wed Jul 27 12:10:12 2016
@@ -0,0 +1,6 @@
+# Job IT tests launcher.
+
+This project runs a test launcher that creates an OSGi instance with only what is required to run Server Side tests.
+Unfurtunately, since OSGi is a multi classloader environment its not possible to perform tests in this bundle, except
+tests over http as any references made to APIs will get resolved with the wrong classloader and so wont be able to 
+interact with OSGi. Hence the tests are in a separate bundle that is loaded by the launchpad.
\ No newline at end of file

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/README.md
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/README.md
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml Wed Jul 27 12:10:12 2016
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>10</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.jobs-it</artifactId>
+    <packaging>jar</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <name>Apache Sling Jobs Integration Tests</name>
+    <description>
+        Integration testing Support for Job processing using message passing..
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/commons/mom/examples/jobs/it</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/commons/mom/examples/jobs/it</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it</url>
+    </scm>
+
+    <properties>
+        <site.jira.version.id>12315369</site.jira.version.id>
+        <sling.java.version>7</sling.java.version>
+        <exam.version>4.4.0</exam.version>
+        <url.version>2.4.5</url.version>
+        <pax.url.version>2.1.0</pax.url.version>
+        <bundle.build.dir>${basedir}/target</bundle.build.dir>
+        <bundle.file.name>${bundle.build.dir}/${project.build.finalName}.jar</bundle.file.name>
+        <min.port>37000</min.port>
+        <max.port>37999</max.port>
+    </properties>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.crankstart.launcher</artifactId>
+            <version>1.9.9-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.testing</artifactId>
+            <version>2.0.16</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jmock</groupId>
+                    <artifactId>jmock-junit4</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.json</artifactId>
+            <version>2.0.10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.1</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.6</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.7.6</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/CheckRootIT.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/CheckRootIT.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/CheckRootIT.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/CheckRootIT.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,51 @@
+package org.apache.sling.jobs.it;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.sling.commons.testing.junit.Retry;
+import org.apache.sling.commons.testing.junit.RetryRule;
+import org.apache.sling.crankstart.junit.CrankstartSetup;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ieb on 07/04/2016.
+ */
+public class CheckRootIT {
+
+
+    @Rule
+    public final RetryRule retryRule = new RetryRule();
+
+    private DefaultHttpClient client;
+
+
+    @Before
+    public void setup() throws IOException {
+        client = new DefaultHttpClient();
+    }
+
+    @Test
+    @Retry(timeoutMsec=Models.LONG_TIMEOUT_MSEC, intervalMsec=Models.STD_INTERVAL)
+    public void testHttpRoot() throws Exception {
+        final HttpUriRequest get = new HttpGet(TestSuiteLauncherIT.crankstartSetup.getBaseUrl());
+        HttpResponse response = null;
+        try {
+            response = client.execute(get);
+            assertEquals("Expecting page not found at " + get.getURI(), 404, response.getStatusLine().getStatusCode());
+        } finally {
+            Models.closeConnection(response);
+        }
+    }
+
+
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/CheckRootIT.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/Models.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/Models.java?rev=1754255&view=auto
==============================================================================
--- sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/Models.java (added)
+++ sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/Models.java Wed Jul 27 12:10:12 2016
@@ -0,0 +1,28 @@
+package org.apache.sling.jobs.it;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+
+/**
+ * Created by ieb on 07/04/2016.
+ */
+public class Models {
+    public static final int LONG_TIMEOUT_SECONDS = 2; // TODO 10
+    public static final int LONG_TIMEOUT_MSEC = LONG_TIMEOUT_SECONDS * 1000;
+    public static final int STD_INTERVAL = 250;
+
+    static final String[] DEFAULT_MODELS = {
+            "/crankstart-model.txt",
+            "/provisioning-model/base.txt",
+            "/provisioning-model/jobs-runtime.txt",
+            "/provisioning-model/crankstart-test-support.txt"
+    };
+
+    static void closeConnection(HttpResponse r) throws IOException {
+        if(r != null && r.getEntity() != null) {
+            EntityUtils.consume(r.getEntity());
+        }
+    }
+}

Propchange: sling/trunk/contrib/commons/mom/examples/jobs/it/src/test/java/org/apache/sling/jobs/it/Models.java
------------------------------------------------------------------------------
    svn:eol-style = native