http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/jndi-names.md ---------------------------------------------------------------------- diff --git a/docs/jndi-names.md b/docs/jndi-names.md new file mode 100644 index 0000000..caec21c --- /dev/null +++ b/docs/jndi-names.md @@ -0,0 +1,372 @@ +index-group=Unrevised +type=page +status=published +title=JNDI Names +~~~~~~ + +<a name="JNDINames-What'sMyBean'sJNDIName?"></a> +# What's My Bean's JNDI Name? +There are two things to keep in mind before you start reading: + +1 OpenEJB provides a default JNDI name to your EJB. +2 You can customize the JNDI name. + +<a name="JNDINames-DefaultJNDIname"></a> +## Default JNDI name +The default JNDI name is in the following format: + + {deploymentId}{interfaceType.annotationName} + +Lets try and understand the above format. Both *deploymentId* and +*interfaceType.annotationName* are pre-defined variables. There are other +pre-defined variables available which you could use to customize the JNDI +name format. + +<a name="JNDINames-JNDINameFormatting"></a> +# JNDI Name Formatting + +The *openejb.jndiname.format* property allows you to supply a template for +the global JNDI names of all your EJBs. With it, you have complete control +over the structure of the JNDI layout can institute a design pattern just +right for your client apps. See the [Service Locator](service-locator.html) + doc for clever ways to use the JNDI name formatting functionality in +client code. +<table class="mdtable"> +<tr><td>variable</td><td> description</td></tr> +<tr><td>moduleId</td><td> Typically the name of the ejb-jar file<br> or the <ejb-jar id=""> id value if specified</td></tr> +<tr><td>ejbType</td><td> STATEFUL, STATELESS, BMP_ENTITY, CMP_ENTITY, or MESSAGE_DRIVEN</td></tr> +<tr><td>ejbClass</td><td> for a class named org.acme.superfun.WidgetBean results in org.acme.superfun.WidgetBean</td></tr> +<tr><td>ejbClass.simpleName</td><td> for a class named org.acme.superfun.WidgetBean results in WidgetBean</td></tr> +<tr><td>ejbClass.packageName</td><td> for a class named org.acme.superfun.WidgetBean results in org.acme.superfun</td></tr> +<tr><td>ejbName</td><td> The ejb-name as specified in xml or via the 'name' attribute in an @Stateful, @Stateless, or @MessageDriven annotation</td></tr> +<tr><td>deploymentId</td><td> The unique system id for the ejb. Typically the ejbName unless specified in the openejb-jar.xml or via changing the openejb.deploymentId.format</td></tr> +<tr><td>interfaceType</td><td> see interfaceType.annotationName</td></tr> +<tr><td>interfaceType.annotationName</td><td> Following the EJB 3 annotations @RemoteHome, @LocalHome, @Remote and @Local +RemoteHome (EJB 2 EJBHome) +LocalHome (EJB 2 EJBLocalHome) +Remote (EJB 3 Business Remote) +Local (EJB 3 Business Local) +Endpoint (EJB webservice endpoint)</td></tr> +<tr><td>interfaceType.annotationNameLC</td><td> This is the same as interfaceType.annotationName, but all in lower case.</td></tr> +<tr><td>interfaceType.xmlName</td><td> Following the ejb-jar.xml descriptor elements <home>, <local-home>, <business-remote>, <business-local>, and <service-endpoint>: +home (EJB 2 EJBHome) +local-home (EJB 2 EJBLocalHome) +business-remote (EJB 3 Business Remote) +business-local (EJB 3 Business Local) +service-endpoint (EJB webservice endpoint)</td></tr> +<tr><td>interfaceType.xmlNameCc</td><td> Camel-case version of interfaceType.xmlName: +Home (EJB 2 EJBHome) +LocalHome (EJB 2 EJBLocalHome) +BusinessRemote (EJB 3 Business Remote) +BusinessLocal (EJB 3 Business Local) +ServiceEndpoint (EJB webservice endpoint)</td></tr> +<tr><td>interfaceType.openejbLegacyName</td><td>Following the OpenEJB 1.0 hard-coded format: +(empty string) (EJB 2 EJBHome) +Local (EJB 2 EJBLocalHome) +BusinessRemote (EJB 3 Business Remote) +BusinessLocal (EJB 3 Business Local) +ServiceEndpoint (EJB webservice endpoint)</td></tr> +<tr><td>interfaceClass</td><td> +(business) for a class named org.acme.superfun.WidgetRemote results in org.acme.superfun.WidgetRemote<br> +(home) for a class named org.acme.superfun.WidgetHome results in org.acme.superfun.WidgetHome</td></tr> +<tr><td>interfaceClass.simpleName</td><td> +(business) for a class named org.acme.superfun.WidgetRemote results in WidgetRemote +(home) for a class named org.acme.superfun.WidgetHome results in WidgetHome</td></tr> +<tr><td>interfaceClass.packageName</td><td> for a class named org.acme.superfun.WidgetRemote results in org.acme.superfun</td></tr> +</table> +<a name="JNDINames-SettingtheJNDIname"></a> +# Setting the JNDI name + +It's possible to set the desired jndi name format for the whole server +level, an ejb-jar, an ejb, an ejb's "local" interface +(local/remote/local-home/home), and for an individual interface the ejb +implements. More specific jndi name formats act as an override to any more +general formats. The most specific format dictates the jndi name that will +be used for any given interface of an ejb. It's possible to specify a +general format for your server, override it at an ejb level and override +that further for a specific interface of that ejb. + +<a name="JNDINames-ViaSystemproperty"></a> +## Via System property + +The jndi name format can be set on a server level via a _system property_, +for example: + + + $ ./bin/openejb start + -Dopenejb.jndiname.format=\{ejbName}/\{interfaceClass}" + + +As usual, other ways of specifying system properties are via the +conf/system.properties file in a standalone server, or via the +InitialContext properties when embedded. + +<a name="JNDINames-Viapropertiesintheopenejb-jar.xml"></a> +## Via properties in the openejb-jar.xml + +It's possible to set the openejb.jndiname.format for an ejb-jar jar in a +META-INF/openejb-jar.xml file as follows: + + + <openejb-jar> + <properties> + openejb.deploymentId.format = {ejbName} + openejb.jndiname.format = {deploymentId}{interfaceType.annotationName} + </properties> + </openejb-jar> + + +<a name="JNDINames-Viathe<jndi>tagforaspecificejb"></a> +## Via the <jndi> tag for a specific ejb + +The following sets the name specifically for the interface +org.superbiz.Foo. + + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <jndi name="foo" interface="org.superbiz.Foo"/> + </ejb-deployment> + </openejb-jar> + + +Or more generally... + + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <jndi name="foo" interface="Remote"/> + </ejb-deployment> + </openejb-jar> + + +Or more generally still... + + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <jndi name="foo"/> + </ejb-deployment> + </openejb-jar> + + +The 'name' attribute can still use templates if it likes, such as: + + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <jndi name="ejb/{interfaceClass.simpleName}" interface="org.superbiz.Foo"/> + </ejb-deployment> + </openejb-jar> + + +<a name="JNDINames-Multiple<jndi>tags"></a> +### Multiple <jndi> tags + +Multiple <jndi> tags are allowed making it possible for you to be as +specific as you need about the jndi name of each interface or each logical +group of iterfaces (Local, Remote, LocalHome, RemoteHome). + +Given an ejb, FooBean, with the following interfaces: + - business-local: org.superbiz.LocalOne + - business-local: org.superbiz.LocalTwo + - business-remote: org.superbiz.RemoteOne + - business-remote: org.superbiz.RemoteTwo + - home: org.superbiz.FooHome + - local-home: org.superbiz.FooLocalHome + +The following four examples would yield the same jndi names. The intention +with these examples is to show the various ways you can isolate specific +interfaces or types of interfaces to gain more specific control on how they +are named. + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <jndi name="LocalOne" interface="org.superbiz.LocalOne"/> + <jndi name="LocalTwo" interface="org.superbiz.LocalTwo"/> + <jndi name="RemoteOne" interface="org.superbiz.RemoteOne"/> + <jndi name="RemoteTwo" interface="org.superbiz.RemoteTwo"/> + <jndi name="FooHome" interface="org.superbiz.FooHome"/> + <jndi name="FooLocalHome" interface="org.superbiz.FooLocalHome"/> + </ejb-deployment> + </openejb-jar> + +Or + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <!-- applies to LocalOne and LocalTwo --> + <jndi name="{interfaceClass.simpleName}" interface="Local"/> + + <!-- applies to RemoteOne and RemoteTwo --> + <jndi name="{interfaceClass.simpleName}" interface="Remote"/> + + <!-- applies to FooHome --> + <jndi name="{interfaceClass.simpleName}" interface="RemoteHome"/> + + <!-- applies to FooLocalHome --> + <jndi name="{interfaceClass.simpleName}" interface="LocalHome"/> + </ejb-deployment> + </openejb-jar> + +Or + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <!-- applies to RemoteOne, RemoteTwo, FooHome, and FooLocalHome --> + <jndi name="{interfaceClass.simpleName}"/> + + <!-- these two would count as an override on the above format --> + <jndi name="LocalOne" interface="org.superbiz.LocalOne"/> + <jndi name="LocalTwo" interface="org.superbiz.LocalTwo"/> + </ejb-deployment> + </openejb-jar> + +or + + <openejb-jar> + <ejb-deployment ejb-name="FooBean"> + <!-- applies to LocalOne, LocalTwo, RemoteOne, RemoteTwo, FooHome, and FooLocalHome --> + <jndi name="{interfaceClass.simpleName}"/> + </ejb-deployment> + </openejb-jar> + + +<a name="JNDINames-ChangingtheDefaultSetting"></a> +# Changing the Default Setting + +*You are responsible for ensuring the names don't conflict.* + +<a name="JNDINames-Conservativesettings"></a> +### Conservative settings + +A very conservative setting such as + + "{deploymentId}/{interfaceClass}" + +would guarantee that each and every single interface is bound to JNDI. If +your bean had a legacy EJBObject interface, three business remote +interfaces, and two business local interfaces, this pattern would result in +*six* proxies bound into JNDI. +<pre> + - {deploymentId}/{interfaceClass.simpleName} + - {moduleId}/{ejbName}/{interfaceClass} + - {ejbName}/{interfaceClass} + - {moduleId}/{ejbClass}/{interfaceClass} + - {ejbClass}/{interfaceClass} + - {ejbClass}/{interfaceClass.simpleName} + - {ejbClass.simpleName}/{interfaceClass.simpleName} + - {interfaceClass}/{ejbName} +</pre> +Bordeline optimistic: +<pre> + - {moduleId}/{interfaceClass} + - {interfaceClass} +</pre> +The above two settings would work if you the interface wasn't shared by +other beans. + +<a name="JNDINames-Pragmaticsettings"></a> +### Pragmatic settings + +A more middle ground setting such as +"{deploymentId}/{interfaceType.annotationName}" would guarantee that at +least one proxy of each interface type is bound to JNDI. If your bean had +a legacy EJBObject interface, three business remote interfaces, and two +business local interfaces, this pattern would result in *three* proxies +bound into JNDI: one proxy dedicated to your EJBObject interface; one proxy +implementing all three business remote interfaces; one proxy implementing +the two business local interfaces. + +Similarly pragmatic settings would be +<pre> + - {moduleId}/{ejbClass}/{interfaceType.annotationName} + - {ejbClass}/{interfaceType.xmlName} + - {ejbClass.simpleName}/{interfaceType.xmlNameCc} + - {interfaceType}/{ejbName} + - {interfaceType}/{ejbClass} +</pre> +<a name="JNDINames-Optimisticsettings"></a> +### Optimistic settings + +A very optimistic setting such as "{deploymentId}" would guarantee only +one proxy for the bean will be bound to JNDI. This would be fine if you +knew you only had one type of interface in your beans. For example, only +business remote interfaces, or only business local interfaces, or only an +EJBObject interface, or only an EJBLocalObject interface. + +If a bean in the app did have more than one interface type, one business +local and one business remote for example, by default OpenEJB will reject +the app when it detects that it cannot bind the second interface. This +strict behavior can be disabled by setting the +*openejb.jndiname.failoncollision* system property to _false_. When this +property is set to false, we will simply log an error that the second proxy +cannot be bound to JNDI, tell you which ejb is using that name, and +continue loading your app. + +Similarly optimistic settings would be: +<pre> + - {ejbName} + - {ejbClass} + - {ejbClass.simpleName} + - {moduleId}/{ejbClass.simpleName} + - {moduleId}/{ejbName} +</pre> +<a name="JNDINames-AdvancedDetailsonEJB3.0BusinessProxies(thesimplepart)"></a> +### Advanced Details on EJB 3.0 Business Proxies (the simple part) + +If you implement your business interfaces, your life is simple as your +proxies will also implement your business interfaces of the same type. +Meaning any proxy OpenEJB creates for a business local interface will also +implement your other business local interfaces. Similarly, any proxy +OpenEJB creates for a business remote interface will also implement your +other business remote interfaces. + +<a name="JNDINames-AdvancedDetailsonEJB3.0BusinessProxies(thecomplicatedpart)"></a> +### Advanced Details on EJB 3.0 Business Proxies (the complicated part) + +*Who should read?* +Read this section of either of these two apply to you: + - You do not implement your business interfaces in your bean class + - One or more of your business remote interfaces extend from javax.rmi.Remote + +If neither of these two items describe your apps, then there is no need to +read further. Go have fun. + +<a name="JNDINames-Notimplementingbusinessinterfaces"></a> +### Not implementing business interfaces + +If you do not implement your business interfaces it may not be possible for +us to implement all your business interfaces in a single interface. +Conflicts in the throws clauses and the return values can occur as detailed [here](multiple-business-interface-hazzards.html) +. When creating a proxy for an interface we will detect and remove any +other business interfaces that would conflict with the main interface. + +<a name="JNDINames-Businessinterfacesextendingjavax.rmi.Remote"></a> +### Business interfaces extending javax.rmi.Remote + +Per spec rules many runtime exceptions (container or connection related) +are thrown from javax.rmi.Remote proxies as java.rmi.RemoteException which +is not a runtime exception and must be throwable via the proxy as a checked +exception. The issue is that conflicting throws clauses are actually +removed for two interfaces sharing the same method signature. For example +two methods such as these: + - InterfaceA: void doIt() throws Foo; + - InterfaceB: void doIt() throws RemoteException; + +can be implemented by trimming out the conflicting throws clauses as +follows: + - Implementation: void doIt(){} + +This is fine for a bean class as it does not need to throw the RMI required +javax.rmi.RemoteException. However if we create a proxy from these two +interfaces it will also wind up with a 'doIt(){}' method that cannot throw +javax.rmi.RemoteException. This is very bad as the container does need to +throw RemoteException to any business interfaces extending java.rmi.Remote +for any container related issues or connection issues. If the container +attempts to throw a RemoteException from the proxies 'doIt(){}' method, it +will result in an UndeclaredThrowableException thrown by the VM. + +The only way to guarantee the proxy has the 'doIt() throws RemoteException +{}' method of InterfaceB is to cut out InterfaceA when we create the proxy +dedicated to InterfaceB.
http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/jpa-concepts.md ---------------------------------------------------------------------- diff --git a/docs/jpa-concepts.md b/docs/jpa-concepts.md new file mode 100644 index 0000000..942d0fb --- /dev/null +++ b/docs/jpa-concepts.md @@ -0,0 +1,220 @@ +index-group=Unrevised +type=page +status=published +title=JPA Concepts +~~~~~~ +<a name="JPAConcepts-JPA101"></a> +# JPA 101 + +If there's one thing you have to understand to successfully use JPA (Java +Persistence API) it's the concept of a *Cache*. Almost everything boils +down to the Cache at one point or another. Unfortunately the Cache is an +internal thing and not exposed via the JPA API classes, so it not easy to +touch or feel from a coding perspective. + +Here's a quick cheat sheet of the JPA world: + + - A **Cache** is a **copy of data**, copy meaning pulled from but living +outside the database. + - **Flushing** a Cache is the act of putting modified data back into the +database. + - A **PersistenceContext** is essentially a Cache. It also tends to have +it's own non-shared database connection. + - An **EntityManager** represents a PersistenceContext (and therefore a +Cache) + - An **EntityManagerFactory** creates an EntityManager (and therefore a +PersistenceContext/Cache) + +Comparing `RESOURCE_LOCAL` and `JTA` persistence contexts + +With <persistence-unit transaction-type="**RESOURCE_LOCAL**"> **you** are +responsible for EntityManager (PersistenceContext/Cache) creating and +tracking... + +- You **must** use the **EntityManagerFactory** to get an EntityManager +- The resulting **EntityManager** instance **is** a +PersistenceContext/Cache +- An **EntityManagerFactory** can be injected via the **@PersistenceUnit** +annotation only (not @PersistenceContext) +- You are **not** allowed to use @PersistenceContext to refer to a unit +of type RESOURCE_LOCAL +- You **must** use the **EntityTransaction** API to begin/commit around +**every** call to your EntityManger +- Calling entityManagerFactory.createEntityManager() twice results in +**two** separate EntityManager instances and therefor **two** separate +PersistenceContexts/Caches. +- It is **almost never** a good idea to have more than one **instance** of +an EntityManager in use (don't create a second one unless you've destroyed +the first) + +With <persistence-unit transaction-type="**JTA**"> the **container** +will do EntityManager (PersistenceContext/Cache) creating and tracking... + +- You **cannot** use the **EntityManagerFactory** to get an EntityManager +- You can only get an **EntityManager** supplied by the **container** +- An **EntityManager** can be injected via the **@PersistenceContext** +annotation only (not @PersistenceUnit) +- You are **not** allowed to use @PersistenceUnit to refer to a unit of +type JTA +- The **EntityManager** given by the container is a **reference** to the +PersistenceContext/Cache associated with a JTA Transaction. +- If no JTA transaction is in progress, the EntityManager **cannot be +used** because there is no PersistenceContext/Cache. +- Everyone with an EntityManager reference to the **same unit** in the +**same transaction** will automatically have a reference to the **same +PersistenceContext/Cache** +- The PersistenceContext/Cache is **flushed** and cleared at JTA +**commit** time + +<a name="JPAConcepts-Cache==PersistenceContext"></a> +# Cache == PersistenceContext + +The concept of a database cache is an extremely important concept to be +aware of. Without a copy of the data in memory (i.e. a cache) when you +call account.getBalance() the persistence provider would have to go read +the value from the database. Calling account.getBalance() several times +would cause several trips to the database. This would obviously be a big +waste of resources. The other side of having a cache is that when you call +account.setBalance(5000) it also doesn't hit the database (usually). When +the cache is "flushed" the data in it is sent to the database via as many +SQL updates, inserts and deletes as are required. That is the basics of +java persistence of any kind all wrapped in a nutshell. If you can +understand that, you're good to go in nearly any persistence technology +java has to offer. + +Complications can arise when there is more than one +PersistenceContext/Cache relating the same data in the same transaction. +In any given transaction you want exactly one PersistenceContext/Cache for +a given set of data. Using a JTA unit with an EntityManager +created by the container will always guarantee that this is the case. With +a RESOURCE_LOCAL unit and an EntityManagerFactory you should create and use +exactly one EntityManager instance in your transaction to ensure there is +only one active PersistenceContext/Cache for the given set of data active +against the current transaction. + +<a name="JPAConcepts-CachesandDetaching"></a> +# Caches and Detaching + +Detaching is the concept of a persistent object **leaving** the +PersistenceContext/Cache. Leaving means that any updates made to the +object are **not** reflected in the PersistenceContext/Cache. An object will +become Detached if it somehow **lives longer** or is **used outside** the scope +of the PersistenceContext/Cache. + +For a JTA unit, the PersistenceContext/Cache will live as long as +the transaction does. When a transaction completes (commits or rollsback) +all objects that were in the PersistenceContext/Cache are Detached. You +can still use them, but they are no longer associated with a +PersistenceContext/Cache and modifications on them will **not** be reflected +in a PersistenceContext/Cache and therefore not the database either. + +Serializing objects that are currently in a PersistenceContext/Cache will +also cause them to Detach. + +In some cases objects or collections of objects that become Detached may +not have all the data you need. This can be because of lazy loading. With +lazy loading, data isn't pulled from the database and into the +PersistenceContext/Cache until it is requested in code. In many cases the +Collections of persistent objects returned from an +javax.persistence.Query.getResultList() call are completely empty until you +iterate over them. A side effect of this is that if the Collection becomes +Detached before it's been fully read it will be permanently empty and of no +use and calling methods on the Detached Collection can cause strange errors +and exceptions to be thrown. If you wish to Detach a Collection of +persistent objects it is always a good idea to iterate over the Collection +at least once. + +You **cannot** call EntityManager.persist() or EntityManager.remove() on a +Detached object. + +Calling EntityManager.merge() will re-attach a Detached object. + +<a name="JPAConcepts-ValidRESOURCE_LOCALUnitusage"></a> +# Valid RESOURCE_LOCAL Unit usage + +Servlets and EJBs can use RESOURCE_LOCAL persistence units through the +EntityManagerFactory as follows: + + <?xml version="1.0" encoding="UTF-8" ?> + <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> + + <!-- Tutorial "unit" --> + <persistence-unit name="Tutorial" transaction-type="RESOURCE_LOCAL"> + <non-jta-data-source>myNonJtaDataSource</non-jta-data-source> + <class>org.superbiz.jpa.Account</class> + </persistence-unit> + + </persistence> + +And referenced as follows + + import javax.persistence.EntityManagerFactory; + import javax.persistence.EntityManager; + import javax.persistence.EntityTransaction; + import javax.persistence.PersistenceUnit; + + public class MyEjbOrServlet ... { + + @PersistenceUnit(unitName="Tutorial") + private EntityManagerFactory factory; + + // Proper exception handling left out for simplicity + public void ejbMethodOrServletServiceMethod() throws Exception { + EntityManager entityManager = factory.createEntityManager(); + + EntityTransaction entityTransaction = entityManager.getTransaction(); + + entityTransaction.begin(); + + Account account = entityManager.find(Account.class, 12345); + + account.setBalance(5000); + + entityTransaction.commit(); + } + + ... + } + + +# Valid JTA Unit usage + +EJBs can use JTA persistence units through the EntityManager as +follows: + + <?xml version="1.0" encoding="UTF-8" ?> + <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> + + <!-- Tutorial "unit" --> + <persistence-unit name="Tutorial" transaction-type="JTA"> + <jta-data-source>myJtaDataSource</jta-data-source> + <non-jta-data-source>myNonJtaDataSource</non-jta-data-source> + <class>org.superbiz.jpa.Account</class> + </persistence-unit> + + </persistence> + +And referenced as follows + + import javax.ejb.Stateless; + import javax.ejb.TransactionAttribute; + import javax.ejb.TransactionAttributeType; + import javax.persistence.EntityManager; + import javax.persistence.PersistenceContext; + + @Stateless + public class MyEjb implements MyEjbInterface { + + @PersistenceContext(unitName = "Tutorial") + private EntityManager entityManager; + + // Proper exception handling left out for simplicity + @TransactionAttribute(TransactionAttributeType.REQUIRED) + public void ejbMethod() throws Exception { + + Account account = entityManager.find(Account.class, 12345); + + account.setBalance(5000); + + } + } http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/jpa-usage.md ---------------------------------------------------------------------- diff --git a/docs/jpa-usage.md b/docs/jpa-usage.md new file mode 100644 index 0000000..6b7cb54 --- /dev/null +++ b/docs/jpa-usage.md @@ -0,0 +1,52 @@ +index-group=Unrevised +type=page +status=published +title=JPA Usage +~~~~~~ +<a name="JPAUsage-Thingstowatchoutfor"></a> +# Things to watch out for + +<a name="JPAUsage-Critical:Alwayssetjta-data-sourceandnon-jta-data-source"></a> +## Critical: Always set jta-data-source and non-jta-data-source + +Always set the value of jta-data-source and non-jta-data-source in your +persistence.xml file. Regardless if targeting your EntityManager usage for +transaction-type="RESOURCE_LOCAL" or transaction-type="TRANSACTION", it's +very difficult to guarantee one or the other will be the only one needed. +Often times the JPA Provider itself will require both internally to do +various optimizations or other special features. + +* The *jta-data-source* should always have it's OpenEJB-specific +'*JtaManaged*' property set to '*true*' (this is the default) +* The *non-jta-data-source* should always have it's OpenEJB-specific +'*JtaManaged*' property set to '*false*'. + +See [Containers and Resources](containers-and-resources.html) + for how to configure 'JtaManaged' and a full list of <Resource> properties +for DataSources. + +<a name="JPAUsage-Bedetachaware"></a> +## Be detach aware + +A warning for any new JPA user is by default all objects will detach at the +end of a transaction. People typically discover this when the go to remove +or update an object they fetched previously and get an exception like "You +cannot perform operation delete on detached object". + +All ejb methods start a transaction unless a) you [configure them otherwise](transaction-annotations.html) +, or b) the caller already has a transaction in progress when it calls the +bean. If you're in a test case or a servlet, it's most likely B that is +biting you. You're asking an ejb for some persistent objects, it uses the +EntityManager in the scope of the transaction started around it's method +and returns some persistent objects, by the time you get them the +transaction has completed and now the objects are detached. + +<a name="JPAUsage-Solutions"></a> +### Solutions +1. Call EntityManager.merge(..) inside the bean code to reattach your +object. +1. Use PersistenceContextType.EXTENDED as in '@PersistenceContext(unitName += "movie-unit", type = PersistenceContextType.EXTENDED)' for EntityManager +refs instead of the default of PersistenceContextType.TRANSACTION. +1. If testing, use a technique to execute transactions in your test code. +That's described here in [Unit testing transactions](unit-testing-transactions.html) http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/local-client-injection.md ---------------------------------------------------------------------- diff --git a/docs/local-client-injection.md b/docs/local-client-injection.md new file mode 100644 index 0000000..7a56f56 --- /dev/null +++ b/docs/local-client-injection.md @@ -0,0 +1,87 @@ +index-group=Unrevised +type=page +status=published +title=Local Client Injection +~~~~~~ +{note:title=OpenEJB 3.1.1 or later required} + +The *@LocalClient* annotation (org.apache.openejb.api.LocalClient) is an +innovation that crosses concepts of an Java EE Application Client with a +plain Java SE client. This particular annotation is focused on clients of +an Embeddable EJB container, i.e. local clients. There is another +annotation in development called @RemoteClient that will be focused on +remote clients; clients running outside the vm the container runs. + +Any clients annotated with @LocalClient will be scanned at deployment time +for usage of injection-related annotations. The references in the +@LocalClient will be processed with the application just as if the class +was a Java EE Application Client module, but with a few slight differences: + +1. Declaring field/method injection points as 'static' is not required +1. References to EntityManagers via @PersistenceContext are allowed +1. References to local business interfaces via @EJB is allowed +1. References to UserTransaction via @Resource is allowed + +As well since this is not a heavyweight Java EE Application Client, you are +not required to use any special packaging or command-line parameters to run +the client. Your client can be a Unit Test or any plain java code that +needs to pull objects from the Embedded EJB container. Classes with +@LocalClient can be placed in a Client module or an EJB module. A given +module may have as many classes annotated with @LocalClient as it wishes. + +<a name="LocalClientInjection-Injection"></a> +# Injection + +The injection occurs via acquiring a LocalInitialContext via the +LocalInitialContextFactory and calling _bind("inject", instance)_ passing +in the instantiated local client object: + + + @LocalClient + public class MoviesTest extends TestCase { + + @EJB + private Movies movies; + + @Resource + private UserTransaction userTransaction; + + @PersistenceContext + private EntityManager entityManager; + + public void setUp() throws Exception { + Properties p = new Properties(); + p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); + InitialContext initialContext = new InitialContext(p); + initialContext.bind("inject", this); + } + + //... other test methods + } + + +<a name="LocalClientInjection-Discovery"></a> +# Discovery + +All EJB modules are scanned for @LocalClient classes, even if those EJB +Modules are inside .war files as with the [Collapsed EAR](collapsed-ear.html) +. As well any modules that contain a META-INF/application-client.xml file +will be scanned for @LocalClient classes. + +If you see the following error message and are absolutely sure the module +containing your @LocalClient class is being properly identified as an EJB +module or a Client module, than it is possible you are seeing some +classloading issues. + +{panel} +javax.naming.NamingException: Unable to find injection meta-data for +org.superbiz.MyClient. Ensure that class was annotated with [email protected] and was successfully discovered and +deployed. +{panel} + +If you encounter this try setting this openejb-specific boot flag so that +annotations will be treated specially and always loaded by the parent +classloader + +`openejb.tempclassloader.skip=annotations` http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/local-server.md ---------------------------------------------------------------------- diff --git a/docs/local-server.md b/docs/local-server.md new file mode 100644 index 0000000..55f45c1 --- /dev/null +++ b/docs/local-server.md @@ -0,0 +1,61 @@ +index-group=Unrevised +type=page +status=published +title=Local Server +~~~~~~ +!http://www.openejb.org/images/diagram-local-server.gif|valign=top, +align=right, hspace=15! +<a name="LocalServer-AccessingEJBsLocally"></a> +# Accessing EJBs Locally + +When OpenEJB embedded in your app, server, IDE, or JUnit, you can use what +we call the Local Server and avoid the network overhead and enjoy an easy +way to embedd OpenEJB. Instead of putting the app in the server, put the +server in the app! + +<a name="LocalServer-Saywhat?!Alocalserver?"></a> +# Say what?! A local server? + +Yes, you read correctly. OpenEJB can be embedded and treated as your very +own personal EJB container. + +If they can have Local and Remote EJB's, why not Local and Remote EJB +Servers too? + +Haven't you ever wanted EJBs without the heavy? I mean you need the "heavy" +eventually, but not while you're developing. Well, there's the advantage of +an EJB implementation that was designed with a very clean and well defined +server-container contract, you can cut the server part out completely! + +So, if you wish to access ejbs locally and not in client/server mode, you +can do so by embedding OpenEJB as a library and accessing ejbs through +OpenEJB's built-in IntraVM (Local) Server. Why would someone want to do +this? +* Your application is a server or other middleware +* You want to write an app that can be both stand alone *and* distributed +* To test your EJBs with JUnit and don't want to start/stop servers and +other nonsense +* Imagine the power from being able to use your IDE debugger to step from +your Client all the way into your EJB and back with no remote debugging +voodoo. + +In this case, your application, test suite, IDE, or client accesses beans +as you would from any other EJB Server. The EJB Server just happens to be +running in the same virtual machine as your application. This EJB Server is +thusly called the IntraVM Server, and, for all intense purposes, your +application an IntraVM Client. + +There are some interesting differences though. The IntraVM Server isn't a +heavyweight server as one normally associates with EJB. It doesn't open +connections, launch threads for processing requests, introduce complex +classloading heirarchies, or any of those "heavy" kind of things. All it +does is dish out proxies to your app that can be used to shoot calls right +into the EJB Container. Very light, very fast, very easy for testing, +debugging, developing, etc. + +<a name="LocalServer-Embedding"></a> +# Embedding + +!http://www.openejb.org/images/diagram-local-server.gif|valign=top, +align=right, hspace=15! +{include:OPENEJBx30:Embedding} http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/lookup-of-other-ejbs-example.md ---------------------------------------------------------------------- diff --git a/docs/lookup-of-other-ejbs-example.md b/docs/lookup-of-other-ejbs-example.md new file mode 100644 index 0000000..d4cd99d --- /dev/null +++ b/docs/lookup-of-other-ejbs-example.md @@ -0,0 +1,149 @@ +index-group=Unrevised +type=page +status=published +title=Lookup of other EJBs Example +~~~~~~ +<a name="LookupofotherEJBsExample-Overview"></a> +# Overview + +This example shows how to configure JNDI to lookup other EJBs using either +the *@EJB* annotation or the *ejb-jar.xml* deployment descriptor. + +There are a couple interesting aspects in this example intended to flush +out some of the more confusing, and perhaps frustrating, aspects of +referring to EJBs. + + - beans themselves do not have JNDI names (this was only recently added in +Java EE 6) + +This is the most frustrating and hard to accept. Java EE 5 does not have a +global namespace and therefore there is no *singular* name for your EJB. +It does not matter what you do to your EJB, there is no standard way to +"give" the bean a name that can be used by the application globally. + + - each EJB owns its own private *java:comp/env* namespace +(*java:comp/env* is not global and cannot be treated that way) + - names do not magically appear in *java:comp/env*, they must be +explicitly added. + - to get a reference to bean *B* in the *java:comp/env* namespace of +bean *A*, bean *A* must declare a reference to bean *B*. + +You read this right. If you have 10 EJBs and all of them want to refer to +bean *B*, then you must declare bean *B* as a reference 10 times (once +for each of the 10 beans). There is no standard way in Java EE 5 to do +this just once for all beans. In Java EE 6 there is a "*java:global*" +namespace, a "*java:app*" namespace, and a "*java:module*" namespace +where names can be defined with the desired scope. Java EE 5 has only +*java:comp*. + +There are two things which make this even more confusing: + + - Servlets have always defined *java:comp/env* differently. In a +webapp, the *java:comp/env* namespace is shared by all servlets. This is +essentially equivalent to the *java:module* namespace in Java EE 6. +Understand there is a conflict in definition here and that for EJBs, +*java:comp* is scoped at the component (the EJB itself) not the module as +with webapps. + - All vendors have some proprietary concept of global JNDI. So you may be +able to lookup "*java:/MyBean*" or "*MyBeanLocal*", but these are +vendor-specific and non-portable. + +As well this example shows some other interesting aspects of referring to +EJBs: + + - Two beans may use the same business interfaces, the interface alone does +not necessarily identify the exact bean + - circular references are possible + +To illustrate all of this, we have two simple @Stateless beans, *RedBean* +and *BlueBean*. Both implement the same business local interface, +*Friend*. Both *RedBean* and *BlueBean* define +*java:comp/env/myFriend* differently which is allowed as *java:comp* is +a namespace that is private to each bean and not visible to other beans -- +so the names do not have to match. + + +<a name="LookupofotherEJBsExample-TheCode"></a> +# The Code + +Here we show the code for *RedBean* and *BlueBean* and their shared +business local interface *Friend*. +{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/RedBean.java|lang=java} +{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/BlueBean.java|lang=java} +{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/main/java/org/superbiz/ejblookup/Friend.java|lang=java} + +The key items in the above are the following: + - *@EJB* has been used at the *class level* to declare *myFriend* in +the *java:comp/env* namespace of each EJB + - because both beans share the *same interface*, *Friend*, we need to +add **beanName** to the *@EJB* usage to specify the exact EJB we want + - for *BlueBean* the *java:comp/env/myFriend* name has been configured +to point to *RedBean* + - for *RedBean* the *java:comp/env/myFriend* name has been configured +to point to *BlueBean* + +<a name="LookupofotherEJBsExample-Alternativetoannotations"></a> +## Alternative to annotations + +If there is a desire to not use annotations, the above annotation usage is +equivalent to the following ejb-jar.xml +{snippet:url=openejb3/examples/lookup-of-ejbs-with-descriptor/src/main/resources/META-INF/ejb-jar.xml|lang=xml} + +<a name="LookupofotherEJBsExample-Writingaunittestfortheexample"></a> +# Writing a unit test for the example + +Writing an unit test for this example is quite simple. We need just to +write a setup method to create and initialize the InitialContext, and then +write our test methods + +{snippet:id=code|url=openejb3/examples/lookup-of-ejbs/src/test/java/org/superbiz/ejblookup/EjbDependencyTest.java|lang=java} + +<a name="LookupofotherEJBsExample-Running"></a> +# Running + +Running the example is fairly simple. In the "lookup-of-ejbs" directory of +the [examples zip](openejb:download.html) +, just run: + +> $ mvn clean install + +Which should create output like the following. + + + ------------------------------------------------------- + T E S T S + ------------------------------------------------------- + Running org.superbiz.ejblookup.EjbDependencyTest + Apache OpenEJB 3.1.5-SNAPSHOT build: 20101129-09:51 + http://tomee.apache.org/ + INFO - openejb.home = +/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs + INFO - openejb.base = +/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs + INFO - Configuring Service(id=Default Security Service, +type=SecurityService, provider-id=Default Security Service) + INFO - Configuring Service(id=Default Transaction Manager, +type=TransactionManager, provider-id=Default Transaction Manager) + INFO - Found EjbModule in classpath: +/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs/target/classes + INFO - Beginning load: +/Users/dblevins/work/openejb-3.1.x/examples/lookup-of-ejbs/target/classes + INFO - Configuring enterprise application: classpath.ear + INFO - Configuring Service(id=Default Stateless Container, type=Container, +provider-id=Default Stateless Container) + INFO - Auto-creating a container for bean BlueBean: +Container(type=STATELESS, id=Default Stateless Container) + INFO - Enterprise application "classpath.ear" loaded. + INFO - Assembling app: classpath.ear + INFO - Jndi(name=BlueBeanLocal) --> Ejb(deployment-id=BlueBean) + INFO - Jndi(name=RedBeanLocal) --> Ejb(deployment-id=RedBean) + INFO - Created Ejb(deployment-id=RedBean, ejb-name=RedBean, +container=Default Stateless Container) + INFO - Created Ejb(deployment-id=BlueBean, ejb-name=BlueBean, +container=Default Stateless Container) + INFO - Deployed Application(path=classpath.ear) + Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.244 sec + + Results : + + Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/managedcontainer-config.md ---------------------------------------------------------------------- diff --git a/docs/managedcontainer-config.md b/docs/managedcontainer-config.md new file mode 100644 index 0000000..1d95e4f --- /dev/null +++ b/docs/managedcontainer-config.md @@ -0,0 +1,26 @@ +index-group=Unrevised +type=page +status=published +title=ManagedContainer Configuration +~~~~~~ + + +A ManagedContainer can be declared via xml in the `<tomee-home>/conf/tomee.xml` file or in a `WEB-INF/resources.xml` file using a declaration like the following. All properties in the element body are optional. + + <Container id="myManagedContainer" type="MANAGED"> + </Container> + +Alternatively, a ManagedContainer can be declared via properties in the `<tomee-home>/conf/system.properties` file or via Java VirtualMachine `-D` properties. The properties can also be used when embedding TomEE via the `javax.ejb.embeddable.EJBContainer` API or `InitialContext` + + myManagedContainer = new://Container?type=MANAGED + +Properties and xml can be mixed. Properties will override the xml allowing for easy configuration change without the need for ${} style variable substitution. Properties are not case sensitive. If a property is specified that is not supported by the declared ManagedContainer a warning will be logged. If a ManagedContainer is needed by the application and one is not declared, TomEE will create one dynamically using default settings. Multiple ManagedContainer declarations are allowed. +# Supported Properties +<table class="mdtable"> +<tr> +<th>Property</th> +<th>Type</th> +<th>Default</th> +<th>Description</th> +</tr> +</table> http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/manual-installation.md ---------------------------------------------------------------------- diff --git a/docs/manual-installation.md b/docs/manual-installation.md new file mode 100644 index 0000000..b00fe81 --- /dev/null +++ b/docs/manual-installation.md @@ -0,0 +1,224 @@ +index-group=Unrevised +type=page +status=published +title=Manual Installation +~~~~~~ + +# Overview + +The manual installation process is significantly harder then the [automatic installation](tomcat.html) + which we normally recommend. In this installation process you will do the +following: + +1. Install openejb.war +1. Download openejb.war from the [download page](http://tomee.apache.org/downloads.html) +1. Make webapps/openejb directory +1. Change to new webapps/openejb directory +1. Unpack the openejb.war file in the new directory +1. Add the OpenEJB listener the conf/server.xml file +1. Update the non-compliant Tomcat annotations-api.jar +1. Add the OpenEJB JavaAgent to the bin/catalina.bat or bin/catalina.bat +script + +##Install openejb.war + +Once Tomcat has been [installed](tomcat-installation.html) +, the OpenEJB plugin for Tomcat can be installed. The war can be obtained +from the [download page](http://tomee.apache.org/downloads.html) + +The commands in this example are executed from within the Tomcat +installation directory. + +<a name="ManualInstallation-UnpackOpenEJBTomcatplugininTomcatwebappsdirectory"></a> +## Unpack OpenEJB Tomcat plugin in Tomcat webapps directory + +Be careful, this is the most error prone step. A web +application does not contain a root directory, so if you unpack it in the +wrong directory, it is difficult to undo. Please, follow this step +closely, and most importantly make sure you execute the unpack command +from within the new webapps/openejb directory + +Due to the structure of war files, you must create a new directory for +OpenEJB, change to the new directory and execute the unpack command from +within the new directory. If you get this wrong, it is difficult to undo, +so follow the steps closely. + +<pre><code> + C:\apache-tomcat-6.0.14>mkdir webapps\openejb + + C:\apache-tomcat-6.0.14>cd webapps\openejb + + C:\apache-tomcat-6.0.14\webapps\openejb>jar -xvf \openejb.war + created: WEB-INF/ + created: WEB-INF/classes/ + created: WEB-INF/classes/org/ + created: WEB-INF/classes/org/apache/ + created: WEB-INF/classes/org/apache/openejb/ + ...snip... + + C:\apache-tomcat-6.0.14\webapps\openejb>dir + Volume in drive C has no label. + Volume Serial Number is 0000-0000 + + Directory of C:\apache-tomcat-6.0.14\webapps\openejb + + 09/21/2007 10:19 AM <DIR> . + 09/21/2007 10:19 AM <DIR> .. + 09/21/2007 10:19 AM 1,000 index.html + 09/21/2007 10:19 AM <DIR> lib + 09/21/2007 10:19 AM 11,358 LICENSE + 09/21/2007 10:19 AM <DIR> META-INF + 09/21/2007 10:19 AM 11,649 NOTICE + 09/21/2007 10:19 AM 1,018 openejb.xml + 09/21/2007 10:19 AM 1,886 README.txt + 09/21/2007 10:19 AM <DIR> tomcat + 09/21/2007 10:19 AM <DIR> WEB-INF + 5 File(s) 26,911 bytes + 6 Dir(s) 4,633,796,608 bytes free + + C:\apache-tomcat-6.0.14\webapps\openejb>cd ..\.. + + C:\apache-tomcat-6.0.14> + + {card:label=Unix}{noformat:nopanel=true} + apache-tomcat-6.0.14$ mkdir webapps/openejb + + apache-tomcat-6.0.14$ cd webapps/openejb/ + + apache-tomcat-6.0.14/webapps/openejb$ jar -xvf path/to/openejb.war + created: WEB-INF/ + created: WEB-INF/classes/ + created: WEB-INF/classes/org/ + created: WEB-INF/classes/org/apache/ + created: WEB-INF/classes/org/apache/openejb/ + ...snip... + + apache-tomcat-6.0.14/webapps/openejb$ ls + LICENSE META-INF/ NOTICE README.txt WEB-INF/ index.html + lib/ openejb.xml tomcat/ + + apache-tomcat-6.0.14/webapps/openejb$ cd ../.. + + apache-tomcat-6.0.14$ + +</code></pre> + +<a name="ManualInstallation-AddtheOpenEJBlistenertoTomcat"></a> +## Add the OpenEJB listener to Tomcat + +All Tomcat listener classes must be available in the Tomcat common class +loader, so the openejb-loader jar must be copied into the Tomcat lib +directory. + + + C:\apache-tomcat-6.0.14>copy webapps\openejb\lib\openejb-loader-3.0.0-SNAPSHOT.jar lib\openejb-loader.jar + 1 file(s) copied. + + apache-tomcat-6.0.14$ cp webapps/openejb/lib/openejb-loader-*.jar lib/openejb-loader.jar + + +Add the following `<Listener +className="org.apache.openejb.loader.OpenEJBListener" />` to your conf/server.xml file to load the OpenEJB listener: + +The snippet is shown below + + <!-- Note: A "Server" is not itself a "Container", so you may not + define subcomponents such as "Valves" at this + level. + Documentation at /docs/config/server.html + --> + + <Server port="8005" shutdown="SHUTDOWN"> + <!-- OpenEJB plugin for tomcat --> + <Listener + className="org.apache.openejb.loader.OpenEJBListener" /> + + <!--APR library loader. Documentation at /docs/apr.html --> + <Listener + className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> + +<a name="ManualInstallation-UpdatetheTomcatannotations-api.jarfile"></a> +## Update the Tomcat annotations-api.jar file + +Tomcat contains an old non-compliant version of the javax.annotation +classes and these invalid classes must be updated so OpenEJB can process +annotations. Simply, replace the annotations-api.jar in the Tomcat lib +directory with the updated annotations-api.jar in the OpenEJB war. + +<pre><code> + +C:\apache-tomcat-6.0.14>copy webapps\openejb\tomcat\annotations-api.jar +lib\annotations-api.jar +Overwrite lib\annotations-api.jar? (Yes/No/All): y + 1 file(s) copied. + +apache-tomcat-6.0.14$ cp webapps/openejb/tomcat/annotations-api.jar +lib/annotations-api.jar + +</code></pre> + +<a name="ManualInstallation-{anchor:javaagent}AddOpenEJBjavaagenttoTomcatstartup"></a> +## Add OpenEJB javaagent to Tomcat startup + +OpenJPA, the Java Persistence implementation used by OpenEJB, currently +must enhanced persistence classes to function properly, and this requires +the installation of a javaagent into the Tomcat startup process. + +First, copy the OpenEJB JavaAgent jar into the lib directory. + +<pre><code> + + C:\apache-tomcat-6.0.14>copy webapps\openejb\lib\openejb-javaagent-3.0.0-SNAPSHOT.jar lib\openejb-javaagent.jar + 1 file(s) copied. + + apache-tomcat-6.0.14$ cp webapps/openejb/lib/openejb-javaagent-*.jar lib/openejb-javaagent.jar + +</code></pre> + +Simply, add the snippet marked below in +bin/catalina.bat (Windows) or bin/catalina.sh (Unix) file to enable the +OpenEJB javaagent: + + if not exist "%CATALINA_BASE%\conf\logging.properties" goto noJuli + set JAVA_OPTS=%JAVA_OPTS% + -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager + -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties" + :noJuli + + # Start of Snippet to add + rem Add OpenEJB javaagent if not exist + "%CATALINA_BASE%\webapps\openejb\lib\openejb-javaagent.jar" goto + noOpenEJBJavaagent set + JAVA_OPTS="-javaagent:%CATALINA_BASE%\webapps\openejb\lib\openejb-javaagent.jar" + %JAVA_OPTS% :noOpenEJBJavaagent + # End of Snippet to add + + + rem ----- Execute The Requested Command + --------------------------------------- + echo Using CATALINA_BASE: %CATALINA_BASE% + echo Using CATALINA_HOME: %CATALINA_HOME% + + + + # Set juli LogManager if it is present + if [OPENEJB: -r "$CATALINA_BASE"/conf/logging.properties ](openejb:--r-"$catalina_base"/conf/logging.properties-.html) + ; then + JAVA_OPTS="$JAVA_OPTS + "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" + "-Djava.util.logging.config.file="$CATALINA_BASE/conf/logging.properties" + fi + + #Start of Snippet to add + if [OPENEJB: -r "$CATALINA_BASE"/webapps/lib/openejb-javaagent.jar ](openejb:--r-"$catalina_base"/webapps/lib/openejb-javaagent.jar-.html) + ; then + JAVA_OPTS=""-javaagent:$CATALINA_BASE/lib/openejb-javaagent.jar" + $JAVA_OPTS" + fi + #End of Snippet to add + + + +##Note: + The example above is an excerpt from the middle of the +bin/catalina.sh file. Search for the this section and add the snippet shown http://git-wip-us.apache.org/repos/asf/tomee/blob/b93bd755/docs/maven.md ---------------------------------------------------------------------- diff --git a/docs/maven.md b/docs/maven.md new file mode 100644 index 0000000..a68c7a9 --- /dev/null +++ b/docs/maven.md @@ -0,0 +1,42 @@ +index-group=Unrevised +type=page +status=published +~~~~~~ +# Maven Information + +This page is intended to provide an insight into basic [Maven](http://maven.apache.org/) usage for users that are not all that familiar with [Maven](http://maven.apache.org/) projects. +It is by no means a tutorial and is designed to be more of a *quickstart* to get you up and running. + +You can find a really good [Maven](http://maven.apache.org/) tutorial here: [http://books.sonatype.com/mvnex-book/reference/public-book.html](http://books.sonatype.com/mvnex-book/reference/public-book.html) + +It is assumed that: + + - You have downloaded and installed [Maven](http://maven.apache.org/) and that you can run **mvn --version** from any command prompt (or console). + - You have downloaded and installed [Subversion](http://subversion.apache.org/) and that you can run **svn --version** from any command prompt or console. + +It is also assumed you have downloaded one of the following: + + - One of the example projects from [http://svn.apache.org/repos/asf/tomee/tomee/trunk/examples]() + - The entire project source from [http://svn.apache.org/repos/asf/tomee/tomee/trunk](http://svn.apache.org/repos/asf/tomee/tomee/trunk) + +Use [Subversion](http://subversion.apache.org/) to checkout the example sources from a console like so: + + svn co http://svn.apache.org/repos/asf/tomee/tomee/trunk/examples/[example] + +Or that you may of course also be using your own project pom.xml + +If you want to use the latest snapshot locate the *<repositories>* section in your pom.xml and ensure the following repository exists: + + <repositories> + <repository> + <id>apache-m2-snapshot</id> + <name>Apache M2 Snapshot Repository</name> + <url>http://repository.apache.org/snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> \ No newline at end of file
