| = Application Composer Getting Started |
| :jbake-type: page |
| :jbake-status: published |
| :index-group: Testing |
| |
| ApplicationComposer API is mainly contained in |
| `org.apache.openejb.testing` package (historically, today we would have |
| called the package `org.apache.tomee.applicationcomposer`). |
| |
| == Dependencies |
| |
| To start using ApplicationComposer you need to add some dependencies. |
| |
| The minimum required one is `openejb-core`: |
| |
| [source,xml] |
| ---- |
| <dependency> |
| <groupId>org.apache.openejb</groupId> |
| <artifactId>openejb-core</artifactId> |
| <version>${openejb.version></version> |
| </dependency> |
| ---- |
| |
| If you need JAXRS services you'll add (or replace thanks to transitivity |
| of maven) `openejb-cxf-rs`: |
| |
| [source,xml] |
| ---- |
| <dependency> |
| <groupId>org.apache.openejb</groupId> |
| <artifactId>openejb-cxf-rs</artifactId> |
| <version>${openejb.version></version> |
| </dependency> |
| ---- |
| |
| If you need JAXWS services you'll add (or replace thanks to transitivity |
| of maven) `openejb-cxf`: |
| |
| [source,xml] |
| ---- |
| <dependency> |
| <groupId>org.apache.openejb</groupId> |
| <artifactId>openejb-cxf</artifactId> |
| <version>${openejb.version></version> |
| </dependency> |
| ---- |
| |
| etc... |
| |
| == ApplicationComposer Components |
| |
| === @Module |
| |
| An ApplicationComposer needs at minimum a module (the application you |
| need to deploy). |
| |
| To do so you have two cases: |
| |
| * before TomEE 2.x: you can only write method(s) decorated with |
| `@Module` |
| * since TomEE 2.x: you can skip it and use `@Classes` directly on the |
| ApplicationComposer class as a shortcut for: |
| + |
| @Module public WebApp app() \{ return new WebApp(); } |
| |
| The expected returned type of these methods are in |
| `org.apache.openejb.jee` package: |
| |
| * `Application`: entry point to create an ear |
| * `WebApp`: a web application |
| * `EjbJar`: an ejb module |
| * `EnterpriseBean` children: a simple EJB |
| * `Persistence`: a persistence module with multiple units |
| * `PersistenceUnit`: a simple unit (automatically wrapped in a |
| `Persistence`) |
| * `Connector`: a JCA connector module |
| * `Beans`: a CDI module, |
| * `Class[]` or `Class`: a set of classes scanned to discover annotations |
| |
| Note that for easiness `@Classes` was added to be able to describe a |
| module and some scanned classes. For instance the following snippet will |
| create a web application with classes C1, C2 as CDI beans and E1 as an |
| EJB automatically: |
| |
| [source,java] |
| ---- |
| @Module |
| @Classes(cdi = true, value = { C1.class, C2.class, E1.class }) |
| public WebApp app() { |
| return new WebApp(); |
| } |
| ---- |
| |
| === @Configuration |
| |
| Often you need to customize a bit the container or at least create some |
| resources like test databases. To do so you can create a method |
| returning `Properties` which will be the container properties. |
| |
| Note: to simplify writing properties you can use `PropertiesBuilder` |
| util class which is just a fluent API to write properties. |
| |
| In these properties you can reuse OpenEJB/TomEE property syntax for |
| resources. |
| |
| Here is a sample: |
| |
| [source,java] |
| ---- |
| @Configuration |
| public Properties configuration() { |
| return new PropertiesBuilder() |
| .p("db", "new://Resource?type=DataSource") |
| .p("db.JdbcUrld", "jdbc:hsqldb:mem:test") |
| .build(); |
| } |
| ---- |
| |
| Since TomEE 2.x you can also put properties on ApplicationComposer class |
| using `@ContainerProperties` API: |
| |
| [source,java] |
| ---- |
| @ContainerProperties({ |
| @ContainerProperties.Property(name = "db", value = "new://Resource?type=DataSource"), |
| @ContainerProperties.Property(name = "db.JdbcUrl", value = "jdbc:hsqldb:mem:test") |
| }) |
| public class MyAppComposer() { |
| // ... |
| } |
| ---- |
| |
| === @Component |
| |
| Sometimes you need to customize a container component. The most common |
| use case is the security service to mock a little bit authorization if |
| you don't care in your test. |
| |
| To do so just write a method decorated with `@Component` returning the |
| instance you desire. |
| |
| Components in TomEE are stored in a container Map and the key needs to |
| be a `Class`. This one is deduced from the returned type of the |
| `@Component` method: |
| |
| [source,java] |
| ---- |
| @Component |
| public SecurityService mockSecurity() { |
| return new MySecurityService(); |
| } |
| ---- |
| |
| == How to run it? |
| |
| === JUnit |
| |
| If you use JUnit you have mainly 2 solutions to run you "model" using |
| the ApplicationComposer: |
| |
| * using `ApplicationComposer` runner: |
| + |
| @RunWith(ApplicationComposer.class) public class MyTest \{ // ... } |
| * using `ApplicationComposerRule` rule: |
| + |
| public class MyTest \{ `@Rule` // or `@ClassRule` if you want the |
| container/application lifecycle be bound to the class and not test |
| methods public final ApplicationComposerRule rule = new |
| ApplicationComposerRule(this); } |
| |
| Tip: since TomEE 2.x ApplicationComposerRule is decomposed in 2 rules if |
| you need: `ContainerRule` and `DeployApplication`. Using JUnit |
| `RuleChain` you can chain them to get the samebehavior as |
| `ApplicationComposerRule` or better deploy multiple ApplicationComposer |
| models and controlling their deployment ordering (to mock a remote |
| service for instance). |
| |
| Finally just write `@Test` method using test class injections as if the |
| test class was a managed bean! |
| |
| === TestNG |
| |
| TestNG integration is quite simple today and mainly |
| `ApplicationComposerListener` class you can configure as a listener to |
| get ApplicationComposer features. |
| |
| Finally just write TestNG `@Test` method using test class injections as |
| if the test class was a managed bean! |
| |
| === Standalone |
| |
| Since TomEE 2.x you can also use `ApplicationComposers` to directly run |
| you ApplicationComposer model as a standalone application: |
| |
| [source,java] |
| ---- |
| public class MyApp { |
| public static void main(String[] args) { |
| ApplicationComposers.run(MyApp.class, args); |
| } |
| |
| // @Module, @Configuration etc... |
| } |
| ---- |
| |
| Tip: if `MyApp` has `@PostConstruct` methods they will be respected and |
| if `MyApp` has a constructor taking an array of String it will be |
| instantiated getting the second parameter as argument (ie you can |
| propagate your main parameter to your model to modify your application |
| depending it!) |
| |
| == JUnit Sample |
| |
| [source,java] |
| ---- |
| @Classes(cdi = true, value = { MyService.class, MyOtherService.class }) |
| @ContainerProperties(@ContainerProperties.Property(name = "myDb", value = "new://Resource?type=DataSource")) |
| @RunWith(ApplicationComposer.class) |
| public class MyTest { |
| @Resource(name = "myDb") |
| private DataSource ds; |
| |
| @Inject |
| private MyService service; |
| |
| @Test |
| public void myTest() { |
| // do test using injections |
| } |
| } |
| ---- |
| |
| == Going further |
| |
| If you want to learn more about ApplicationComposer see |
| link:advanced.html[Advanced] page. |