/*
* Copyright 2016 Red Hat, Inc.
*
* Licensed 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.jboss.as.test.integration.batch.deployment;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.OperateOnDeployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.as.arquillian.container.ManagementClient;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.client.helpers.Operations;
import org.jboss.as.test.integration.batch.common.AbstractBatchTestCase;
import org.jboss.as.test.integration.batch.common.BatchExecutionService;
import org.jboss.as.test.integration.batch.common.CountingItemReader;
import org.jboss.as.test.integration.batch.common.CountingItemWriter;
import org.jboss.dmr.ModelNode;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
@RunAsClient
@RunWith(Arquillian.class)
public class JobXmlVisibilityTestCase extends AbstractBatchTestCase {
private static final String EAR = "test-visibility.ear";
private static final String EAR_ISOLATED = "test-visibility-isolated.ear";
private static final String EAR_WITH_LIB = "test-with-lib.ear";
private static final String EAR_WITH_LIB_ISOLATED = "test-isolated-with-lib.ear";
private static final String WAR_WITH_LIB = "test-war-with-lib.war";
@ArquillianResource
// @OperateOnDeployment is required until WFARQ-13 is resolved, any deployment should suffice though
@OperateOnDeployment(EAR)
private ManagementClient managementClient;
@Deployment(name = EAR)
public static EnterpriseArchive visibleEarDeployment() {
return createEar(EAR, "visible");
}
@Deployment(name = EAR_ISOLATED)
public static EnterpriseArchive isolatedEarDeployment() {
return createEar(EAR_ISOLATED, "isolated")
.addAsManifestResource(new StringAsset(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<jboss-deployment-structure>\n" +
" <ear-subdeployments-isolated>true</ear-subdeployments-isolated>\n" +
"</jboss-deployment-structure>"
), "jboss-deployment-structure.xml");
}
@Deployment(name = EAR_WITH_LIB)
public static EnterpriseArchive earWithLibDeployment() {
return createEar(EAR_WITH_LIB, "with-lib")
.addAsLibrary(createJar("lib-in-ear.jar"));
}
@Deployment(name = EAR_WITH_LIB_ISOLATED)
public static EnterpriseArchive isolatedEarWithLibDeployment() {
return createEar(EAR_WITH_LIB_ISOLATED, "isolated-with-lib")
.addAsLibrary(createJar("lib-in-ear.jar"))
.addAsManifestResource(new StringAsset(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<jboss-deployment-structure>\n" +
" <ear-subdeployments-isolated>true</ear-subdeployments-isolated>\n" +
"</jboss-deployment-structure>"
), "jboss-deployment-structure.xml");
}
@Deployment(name = WAR_WITH_LIB)
public static WebArchive warWithLibDeployment() {
return createWar(WAR_WITH_LIB)
.addClasses(CountingItemReader.class, CountingItemWriter.class)
.addAsLibrary(createJar("lib-in-war.jar"));
}
/**
* Tests that all job XML files are visible from the WAR.
*/
@Test
public void testJobXmlIsVisible() throws Exception {
validateJobNames(deploymentAddress(EAR, "war-in-ear-visible.war"), Arrays.asList("test-war.xml", "test-ejb.xml"));
}
/**
* Tests that the WAR can only see the job XML from the WAR and the EJB can only see the job XML from the EJB.
*/
@Test
public void testJobXmlIsIsolated() throws Exception {
validateJobNames(deploymentAddress(EAR_ISOLATED, "war-in-ear-isolated.war"), Collections.singleton("test-war.xml"));
validateJobNames(deploymentAddress(EAR_ISOLATED, "ejb-in-ear-isolated.jar"), Collections.singleton("test-ejb.xml"));
}
/**
* Tests that the WAR can see the job XML from the WAR itself, the EJB and the EAR's global dependency. The EJB
* should be able to see the job XML from the EJB itself and the EAR's global dependency.
*/
@Test
public void testJobXmlIsVisibleJar() throws Exception {
validateJobNames(deploymentAddress(EAR_WITH_LIB, "war-in-ear-with-lib.war"), Arrays.asList("test-war.xml", "test-ejb.xml", "test-jar.xml"));
validateJobNames(deploymentAddress(EAR_WITH_LIB, "ejb-in-ear-with-lib.jar"), Arrays.asList("test-ejb.xml", "test-jar.xml"));
}
/**
* Tests that the WAR can see the job XML from the WAR itself and the EAR's global dependency. The EJB
* should be able to see the job XML from the EJB itself and the EAR's global dependency.
*/
@Test
public void testJobXmlIsIsolatedJar() throws Exception {
validateJobNames(deploymentAddress(EAR_WITH_LIB_ISOLATED, "war-in-ear-isolated-with-lib.war"), Arrays.asList("test-war.xml", "test-jar.xml"));
validateJobNames(deploymentAddress(EAR_WITH_LIB_ISOLATED, "ejb-in-ear-isolated-with-lib.jar"), Arrays.asList("test-ejb.xml", "test-jar.xml"));
}
/**
* Test that a WAR will see the job XML from a direct dependency.
*/
@Test
public void testJobXmlInWar() throws Exception {
validateJobNames(deploymentAddress(WAR_WITH_LIB, null), Arrays.asList("test-war.xml", "test-jar.xml"));
}
private void validateJobNames(final ModelNode address, final Collection<String> expected) throws IOException {
Set<String> jobXmlNames = getJobNames(address);
Assert.assertEquals(expected.size(), jobXmlNames.size());
Assert.assertTrue("Expected the following job XML names: " + expected, jobXmlNames.containsAll(expected));
}
private Set<String> getJobNames(final ModelNode address) throws IOException {
final ModelNode op = Operations.createReadAttributeOperation(address, "job-xml-names");
final ModelNode result = executeOperation(op);
return result.asList()
.stream()
.map(ModelNode::asString)
.collect(Collectors.toSet());
}
@SuppressWarnings("Duplicates")
private ModelNode executeOperation(final ModelNode op) throws IOException {
final ModelControllerClient client = managementClient.getControllerClient();
final ModelNode result = client.execute(op);
if (Operations.isSuccessfulOutcome(result)) {
return Operations.readResult(result);
}
Assert.fail(Operations.getFailureDescription(result).asString());
// Should never be reached
return new ModelNode();
}
private static EnterpriseArchive createEar(final String name, final String suffix) {
return ShrinkWrap.create(EnterpriseArchive.class, name)
.addAsModule(createEjb("ejb-in-ear-" + suffix + ".jar"))
.addAsModule(createWar("war-in-ear-" + suffix + ".war"));
}
private static WebArchive createWar(final String name) {
final WebArchive war = ShrinkWrap.create(WebArchive.class, name)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
addJobXml(war, "test-war");
return war;
}
private static JavaArchive createEjb(final String name) {
final JavaArchive jar = ShrinkWrap.create(JavaArchive.class, name)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
// Add at least one EJB annotated class to make this an EJB JAR
.addClasses(CountingItemReader.class, CountingItemWriter.class, BatchExecutionService.class);
addJobXml(jar, "test-ejb");
return jar;
}
private static JavaArchive createJar(final String name) {
final JavaArchive jar = ShrinkWrap.create(JavaArchive.class, name)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
.addClasses(AbstractBatchTestCase.class);
addJobXml(jar, "test-jar");
return jar;
}
private static ModelNode deploymentAddress(final String deploymentName, final String subDeploymentName) {
if (subDeploymentName == null) {
return Operations.createAddress(
"deployment",
deploymentName,
"subsystem",
"batch-jberet"
);
}
return Operations.createAddress(
"deployment",
deploymentName,
"subdeployment",
subDeploymentName,
"subsystem",
"batch-jberet"
);
}
}