arquillian + shrinkwrap + seam: how to create deployment package - jboss

I have a seam 2.2.2 aplication which I'm migrating to jboss eap 6 (AS7).
As the tests were in the old jboss embedded container, so I started to use arquillian but I could not discover hot to create a deployment package.
This is one of my attempts:
#Deployment
#OverProtocol("Servlet 3.0")
public static Archive<?> createDeployment() throws IOException {
// Build the ear with Maven by hand before run the test!
final EnterpriseArchive ear = ShrinkWrap.createFromZipFile(
EnterpriseArchive.class, new File("../Sin-ear/target/Sin.ear"));
final JavaArchive testjar = ShrinkWrap.createFromZipFile(
JavaArchive.class, new File("./target/test.jar"));
//final JavaArchive testjar = ShrinkWrap.create(JavaArchive.class, "test.jar") //other attempt
// .addPackages(true, "com.miles.knowledge.test");
ear.addAsModule(testjar);
return ear;
}
And it fails when I run the test class as JUnit test (I can see the aplication deployment with no errors):
java.lang.ClassNotFoundException: com.miles.knowledge.test.GreeterTest from [Module "deployment.Sin.ear.Sin.war:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:213)
...
It seems that I have to package the test class into a war package, but I'm kind of lost, I need some help.

This kind of deployment should work (note adding the test class to the war)...
#RunWith(Arquillian.class)
public class JsfTest extends org.jboss.seam.mock.JUnitSeamTest{
#Deployment(name="UserLoginTest")
#OverProtocol("Servlet 3.0")
public static Archive<?> createDeployment(){
EnterpriseArchive er = Deployments.webAppDeployment();
WebArchive web = er.getAsType(WebArchive.class, "WebApp-web.war");
er.addAsModule(Testable.archiveToTest(web));
web.addClasses(JsfTest.class)
.addAsResource(EmptyAsset.INSTANCE, "seam.properties")
.delete("/WEB-INF/web.xml");
web.addAsWebInfResource("mock-web.xml", "web.xml");
return er;
}
}
public class Deployments {
public static EnterpriseArchive webAppDeployment() {
return ShrinkWrap.create(ZipImporter.class, "WebApp.ear")
.importFrom(new File("../WebApp-ear/target/WebApp.ear"))
.as(EnterpriseArchive.class);
}
}

Related

Overridden RabbitSourceConfiguration (app starters) does not work with Spring Cloud Edgware

I'm testing an upgrade of my Spring Cloud DataFlow services from Spring Cloud Dalston.SR4/Spring Boot 1.5.9 to Spring Cloud Edgware/Spring Boot 1.5.9. Some of my services extend source (or sink) components from the app starters. I've found this does not work with Spring Cloud Edgware.
For example, I have overridden org.springframework.cloud.stream.app.rabbit.source.RabbitSourceConfiguration and bound my app to my overridden version. This has previously worked with Spring Cloud versions going back almost a year.
With Edgware, I get the following (whether the app is run standalone or within dataflow):
***************************
APPLICATION FAILED TO START
***************************
Description:
Field channels in org.springframework.cloud.stream.app.rabbit.source.RabbitSourceConfiguration required a bean of type 'org.springframework.cloud.stream.messaging.Source' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.cloud.stream.messaging.Source' in your configuration.
I get the same behaviour with the 1.3.0.RELEASE and 1.2.0.RELEASE of spring-cloud-starter-stream-rabbit.
I override RabbitSourceConfiguration so I can set a header mapper on the AmqpInboundChannelAdapter, and also to perform a connectivity test prior to starting up the container.
My subclass is bound to the Spring Boot application with #EnableBinding(HeaderMapperRabbitSourceConfiguration.class). A cutdown version of my subclass is:
public class HeaderMapperRabbitSourceConfiguration extends RabbitSourceConfiguration {
public HeaderMapperRabbitSourceConfiguration(final MyHealthCheck healthCheck,
final MyAppConfig config) {
// ...
}
#Bean
#Override
public AmqpInboundChannelAdapter adapter() {
final AmqpInboundChannelAdapter adapter = super.adapter();
adapter.setHeaderMapper(new NotificationHeaderMapper(config));
return adapter;
}
#Bean
#Override
public SimpleMessageListenerContainer container() {
if (config.performConnectivityCheckOnStartup()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Attempting connectivity with ...");
}
final Health health = healthCheck.health();
if (health.getStatus() == Status.DOWN) {
LOGGER.error("Unable to connect .....");
throw new UnableToLoginException("Unable to connect ...");
} else if (LOGGER.isInfoEnabled()) {
LOGGER.info("Connectivity established with ...");
}
}
return super.container();
}
}
You really should never do stuff like healthCheck.health(); within a #Bean definition. The application context is not yet fully baked or started; it may, or may not, work depending on the order that beans are created.
If you want to prevent the app from starting, add a bean that implements SmartLifecycle, put the bean in a late phase (high value) so it's started after everything else. Then put your code in start(). autStartup must be true.
In this case, it's being run before the stream infrastructure has created the channel.
Some ordering might have changed from the earlier release but, in any case, performing activity like this in a #Bean definition is dangerous.
You just happened to be lucky before.
EDIT
I just noticed your #EnableBinding is wrong; it should be Source.class. I can't see how that would ever have worked - that's what creates the bean for the channels field of type Source.
This works fine for me after updating stream and the binder to 1.3.0.RELEASE...
#Configuration
public class MySource extends RabbitSourceConfiguration {
#Bean
#Override
public AmqpInboundChannelAdapter adapter() {
AmqpInboundChannelAdapter adapter = super.adapter();
adapter.setHeaderMapper(new MyMapper());
return adapter;
}
}
and
#SpringBootApplication
#EnableBinding(Source.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
If that doesn't work, please edit the question to show your POM.

Arquillian Integration with WildFly 10

Can anyone please guide me on how to use Arquillian with WildFly 10. I have recently migrated my application from JBoss 7 to WildFly 10. Arquillian used to work with JBoss 7, but the same configuration is not working on WildFly 10.
I am able to integrate now, however my EJBs with JNDI names as "java:global/xyz/xyzEMFactor" is failing with following error:
Caused by: java.lang.Exception: {"WFLYCTL0180: Services with missing/unavailable dependencies" => ["jboss.naming.context.java.module.test.test.env.\"com.xyz.abc.poc.knowledge_ba‌​se.ontology.DBContex‌​tBean\".emFactory is missing [jboss.naming.context.java.global.xyz_dal.xyzpEMFactory‌​]"]} at org.jboss.as.controller.client.helpers.standalone.impl.Serve‌​rDeploymentPlanResul‌​tFuture.getActionRes‌​ult(ServerDeployment‌​PlanResultFuture.jav‌​a:134)
Following is my class:
#AccessTimeout(5 * 60 * 60 * 1000)
#StatefulTimeout(-1)
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class DBContextBean<T> {
#Inject
#EJB(lookup = "java:global/xyz_dal/xyzEMFactory")
private xyzEMFactory emFactory;
}
It was because, The testable war file, i was creating a jar as,
#Deployment(name = "xyz_dal", order = 3)
public static Archive<?> createDeployment() {
JavaArchive jar = ShrinkWrap.create(JavaArchive .class, "xyz_dal.jar")
.addClasses(xyzEMFactory.class, DBContextBean.class, xyzDao.class)
.addPackages(true, "com.xyz.abc.poc.entities")
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml").setManifest(new Asset() {
#Override
public InputStream openStream() {
// dependency management
return ManifestBuilder.newInstance()
.addManifestHeader("Dependencies", "xyz,javax.api,deployment.abc_common.jar")
.openStream();
}
});
return jar;
}
It worked when i changed it to
#Deployment(name = "xyz_dal", order = 3)
public static Archive<?> createDeployment() {
WebArchive jar = ShrinkWrap.create(WebArchive.class, "xyz_dal.war")
.addClasses(xyzpEMFactory.class, DBContextBean.class, xyzDao.class)
.addPackages(true, "com.xyz.abc.poc.entities")
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml").setManifest(new Asset() {
#Override
public InputStream openStream() {
// dependency management
return ManifestBuilder.newInstance()
.addManifestHeader("Dependencies", "xyz,javax.api,deployment.abc_common.jar")
.openStream();
}
});
return jar;
}
It was because when i was creating a testable jar,the container wraps the jar in a test.war, and hence the context "java:global/xyz/xyzEMFactory" was not available.
I don't know how this could work in JBoss7 but: either #EJB or #Inject, I presume #Inject, is superfluous. In my experience wildfly is sometimes more rigorous than jboss7 when looking at unclear constructs.
#Inject
#EJB(lookup = "java:global/xyz_dal/xyzEMFactory")
xyzEMFactory emFactory;
CDI can't inject ejbs. What we do sometimes is:
#Produces
#EJB(lookup = "java:global/xyz/xyzEMFactory")
xyzEMFactory emFactory;
Then you can use at other places
#Inject
xyzEMFactory emFactory;
because the ejb-injected bean can be used as Producer-Field.

Test the remote client jndi lookup using arquillian

Setup: arquillian, jboss as 7.1.1.final as a managed Container
I am currently migrating an EJB application from EJB 2.x to 3.x and JBoss 3.x to JBoss AS 7.1.
During this process i would like to get most classes under test and stumbled over arquillian.
While arquillian seems to offer some nice features on inter-bean-functionality i cannot figure out whether or not the testing of remote client features using jndi lookups works or not.
I used the Arquillian Getting started guides on my beans which worked, but since these are using #Inject and in my application jndi lookups are used everywhere i (at least think that i) need to swerve from that path.
Here is the TestCase i created based on Arquillian Getting Started. I explicitly left in all attempts using jndi properties of which i thought they might help.
The Test
should_create_greeting()
works if the Greeter bean using a separate Producer.
#RunWith(Arquillian.class)
public class GreeterTest {
public static final String ARCHIVE_NAME = "test";
Logger logger = Logger.getLogger(GreeterTest.class.getName());
#Deployment
public static Archive<?> createDeployment() {
JavaArchive jar = ShrinkWrap.create(JavaArchive.class, ARCHIVE_NAME + ".jar").addPackage(Greeter.class.getPackage())
.addAsManifestResource("test-persistence.xml", "persistence.xml").addAsManifestResource("OracleGUIDS-ds.xml")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
return jar;
}
/**
* #Inject works using a producer with {#code #Produces}
*/
// #Inject
// Greeter greeter;
#ArquillianResource
Context context;
GreeterRemote greeter;
#Before
public void before() throws Exception {
Map<String, String> env = new HashMap<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.as.naming.InitialContextFactory");
env.put("jboss.naming.client.ejb.context", "true");
// env.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT",
// "false");
// env.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS",
// "false");
// env.put("jboss.naming.client.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED",
// "false");
for (Map.Entry<String, String> entry : env.entrySet()) {
context.addToEnvironment(entry.getKey(), entry.getValue());
}
greeter = (GreeterRemote) context.lookup(ARCHIVE_NAME + "/" + Greeter.class.getSimpleName() + "!"
+ GreeterRemote.class.getName());
}
#Test
public void should_create_greeting() {
Assert.assertEquals("Hello, Earthling!", greeter.createGreeting("Earthling"));
greeter.greet(System.out, "Earthling");
}
}
Is it possible to get this test running with jndi lookup? Am i missing something?
If you want to test the Remote features of a EJB you probably want to run on the client side and not in container.
You can configure the Deployment to be only client side by using #Deployment(testable=false). The #Test methods will then run as if you were a remote client.
Beyond that you can just lookup the bean via the injected Context if you want.
I had the same issue, so in a workaround i just added on the method to be tested the remoteejb as a parameter.
On my ejb:
public List localBean.obtain(RemoteEJB remoteEjb){
return remoteEjb.obtain();
}
Then on the arquillian test :
#Inject
private LocalBean localBean;
#Inject
private RemoteEJB remoteEjb;
#Test
public void test(){
List<Vo>voList = localBean.obtain(remoteEjb);
}
The best part is the remote ejb its injected and on the caller method original
#EJB(lookup="java:global/ear/ejb/RemoteEjb")
private RemoteEJB remoteEjb;

Spring bean loading issue in BIRT designer

I have an issue with Spring not loading beans correctly when run from a script in a BIRT Scripted Data Source, but running OK on its own.
Here's a minimal test case:
The spring bean:
package test;
import org.springframework.stereotype.Component;
#Component
public class TestComponent { }
The context provider:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringContextHolder {
private static ApplicationContext ac;
public static ApplicationContext getApplicationContext() {
if( ac == null ) {
ac = new ClassPathXmlApplicationContext("classpath:beans.xml");
}
return ac;
}
}
beans.xml:
<beans .......>
<context:component-scan base-package="test"></context:component-scan>
<context:annotation-config />
</beans>
And finally the test program which is a simple Eclipse java project having all spring and related jars and the test.jar from above in its build path:
public class cltest {
public static void main(String[] args ) throws BeansException {
System.out.println(test.SpringContextHolder.getApplicationContext().getBean("testComponent"));
}
}
This program runs fine and delivers the bean. But when I run the same jars in BIRT designer (4.3.0) by setting them in the Report classpath preferences, I get an exception:
A BIRT exception occurred. See next exception for more information.
Wrapped org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/C:/Users/xxx/.m2/repository/test/test/0.0.1-SNAPSHOT/test-0.0.1-SNAPSHOT.jar!/test/SpringContextHolder.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 6
The script source is simply:
importPackage(Packages.test);
ts = SpringContextHolder.getApplicationContext().getBean("testComponent");
The exception results from org.springframework.asm.ClassReader where a readShort violates some array boundaries.
Spring version is 3.2.3 RELEASE, Oracle Java 7u25, BIRT Designer 4.3.0.
Can anyone explain what the difference between the two running scenarios is? Probably some class loader issues when the jars are loaded by the eclipse runtime?

Can I inject spring bean from JAR file?

I use Spring 3 in my project.Then I face a problem when I inject spring bean from JAR file. In JAR file, there is class like;
package test;
#Service("CommonService")
public class CommonService {
}
And i already used it like this;
package com.java.test.app;
#Service(value = "OtherService")
public class OtherService {
#Resource(name = "CommonService")
private CommonService service;
}
In my spring-beans.xml;
<context:component-scan base-package="com.java.test.app, test">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
But #Resource annotation doesn't work.Can I inject spring bean from JAR file?
If at runtime your CommonService class is on the classpath and is within the base package you specify with component-scan, then you should be good to go. Try using #Autowired instead of #Resource.