RE: traditional jee deployment for liferay 7

Daniel Niklas, modified 7 Years ago. Junior Member Posts: 46 Join Date: 11/8/10 Recent Posts
Hi,

i don't want to start a new debate about "is OSGI the right approach" like https://web.liferay.com/de/community/forums/-/message_boards/message/71530222.

There are several reasons, why i have to use a traditional jee deployment:


  • use existing processes for deployment to your application server.
    deployment piples (e.g. with jenkins), rolling update strategies, cluster deployments,...
  • use features of your application server.
    You can use features of your application server. In case of wildfly (10/11) you can use all JEE 7 features. For example: EJB, JPA, JTA.
  • use "infrastructure" of your application server
    an application server provides useful "infrastructure". For example caches, connection pools, logging, Messaging Queues.
  • use monitoring of your application server
    you can monitor your applications with the capabilities of your application server. For example: request count, max request time, average request time,



There are other people having similar problems, eg. https://web.liferay.com/de/community/forums/-/message_boards/view_message/94484732. Because of that i decided to write things down and share them on github, have a look at:

https://github.com/daniel-niklas/liferay-jee-deploy

  • what do you think about this approach?
  • is this possible in future Liferay versions?


Best regards
Daniel
thumbnail
Juan Gonzalez, modified 7 Years ago. Liferay Legend Posts: 3089 Join Date: 10/28/08 Recent Posts
Hi Daniel. I myself thought about what you said for Java EE deployments many times. IMO isn't that different as it may seem.

Daniel Niklas:
  • use features of your application server.
    You can use features of your application server. In case of wildfly (10/11) you can use all JEE 7 features. For example: EJB, JPA, JTA.


  • What problems are you having for using EJB, JPA, etc?

    Daniel Niklas:
  • use "infrastructure" of your application server
    an application server provides useful "infrastructure". For example caches, connection pools, logging, Messaging Queues.


  • Same as previous question. Right now I don't see why of any of these features wouldn' t be usable from Liferay 7.

    Daniel Niklas:
  • use monitoring of your application server
    you can monitor your applications with the capabilities of your application server. For example: request count, max request time, average request time,


  • Yes, this can be a problem if you want to have different counters for each "classic" WAR.
    Daniel Niklas, modified 7 Years ago. Junior Member Posts: 46 Join Date: 11/8/10 Recent Posts
    Hi Juan,

    Juan Gonzalez:
    What problems are you having for using EJB, JPA, etc?

    For example you have one EJB and want to inject this into your JSF managed bean:

    @Stateless
    public class MyService {
    
    	@PersistenceContext(unitName = "myJpaPU")
    	private EntityManager em;
    // ...
    }


    @ManagedBean
    @RequestScoped
    public class MyJsfBean {
    
    	@EJB
    	private MyService myService;
    // ...
    }


    When Liferay starts start your "module" as OSGI-WAB, then the application server does not know this deployment. Therefore you can't use this EJB.

    Juan Gonzalez:
    Same as previous question. Right now I don't see why of any of these features wouldn' t be usable from Liferay 7.

    Currently JCache ist not available in JEE 7. So i use the cache from wildfly. This is infinispan.

    For example like so:
    //...
    import org.infinispan.Cache;
    import org.infinispan.manager.CacheContainer;
    
    @Stateless
    public class MyService {
    
    	@Resource(name = "myCacheContainer")
    	private CacheContainer cacheContainer;
    
    	private Cache<string, adresse> adresseCache;
    
    	@PostConstruct
    	public void postConstruct() {
    		adresseCache = cacheContainer.getCache("adresseCache");
    	}
    //...
    }</string,>


    Juan Gonzalez:
    Yes, this can be a problem if you want to have different counters for each "classic" WAR.


    Right, the specific monitoring-data for each deployment are missing, because the application server doesn't know them.

    All these examples cannot be achieve with OSGI-Deployments.
    thumbnail
    Kyle Joseph Stiemann, modified 7 Years ago. Liferay Master Posts: 760 Join Date: 1/14/13 Recent Posts
    Hi Daniel,
    Please check out this post on Tobias's original thread: https://web.liferay.com/community/forums/-/message_boards/message/104382443. It may be helpful for your use case as well.

    - Kyle
    Daniel Niklas, modified 7 Years ago. Junior Member Posts: 46 Join Date: 11/8/10 Recent Posts
    Hi Kyle,

    i don't think, that this helps. The application server must be responsible for scanning classes etc. In my understanding this is the wrong way round.

    Daniel
    thumbnail
    Tobias Liefke, modified 7 Years ago. Junior Member Posts: 78 Join Date: 11/23/12 Recent Posts
    Hi Daniel,

    would have been nice, if you had added a comment to my question about your approach.

    If I understand your repository correctly, you did nothing to access the OSGI bundles / classes from your portlet? It does only contain a simple example portlet? In that case you could add this use case as another checkpoint to your todo list.
    Daniel Niklas, modified 7 Years ago. Junior Member Posts: 46 Join Date: 11/8/10 Recent Posts
    Hi Tobias,

    i'm not sure, if i get us right. What is your use case?
    You can for example user UserLocalServiceUtil. This class is provided from portal-kernel.jar.
    thumbnail
    Tobias Liefke, modified 7 Years ago. Junior Member Posts: 78 Join Date: 11/23/12 Recent Posts
    Hi Daniel,

    you can access all classes from portal-kernel without knowing your github - page.

    My use case is to have access to classes that are located in the Liferay OSGI bundles from my portlet WAR.

    For example DDMTemplateLocalServiceUtil, which was part of portal-kernel until Liferay 6.2, is now located in the OSGI-Bundle com.liferay.dynamic.data.mapping.api. To access that util class I can't put the bundle into my WAR. I need to access the class from the OSGI class loader, as only that one can access the service.

    I had to write a WildFly module which modifies the WAR class loader and is very project specific. I hope you find a solution which is more "versatile".
    Daniel Niklas, modified 7 Years ago. Junior Member Posts: 46 Join Date: 11/8/10 Recent Posts
    Tobias Liefke:
    For example DDMTemplateLocalServiceUtil, which was part of portal-kernel until Liferay 6.2, is now located in the OSGI-Bundle com.liferay.dynamic.data.mapping.api. To access that util class I can't put the bundle into my WAR. I need to access the class from the OSGI class loader, as only that one can access the service.

    ah ok, i get it. I didn't realize yet, that many Local-Services aren't part of portal-kernel.jar in Lifery 7. In my understanding (in Liferay 6.2) the Interfaces are Part of the shared library, but the implementation und the excecution is part of a webapp. For your example ( com.liferay.dynamic.data.mapping.api) the implementation is part of ROOT.war).

    Isn't it the mechanmism of Local-Services?

    So hopefully you only need access to the interfaces, the portal-kernal.jar contains the "client stuff".

    Tobias Liefke:

    I had to write a WildFly module which modifies the WAR class loader and is very project specific. I hope you find a solution which is more "versatile".

    Can you share your code to get an idea of your approach?
    thumbnail
    Tobias Liefke, modified 7 Years ago. Junior Member Posts: 78 Join Date: 11/23/12 Recent Posts
    *LocalServices and *LocalServiceUtil are still part of portal-kernel in Liferay 7 for most of the services.

    But com.liferay.dynamic.data.mapping.api was never part of ROOT.war (even in Liferay 6.2). DDMTemplateLocalServiceUtil was part of another package in portal-kernel.jar, which is now removed in Liferay 7.

    As far as I understand the idea behind OSGI in Liferay 7 and upcoming versions is to down strip ROOT.war and portal-kernel.jar and move nearly all functionality to OSGI bundles - to have a more modular and flexible Liferay architecture, in contrast to the old "monolithic" approach.

    I've got no problem with that - as long as my portlets may still be located in a WAR which is able to use nearly all functionality provided by the JEE container as well - what was the intention of my original post.
    Martin Jonik, modified 7 Years ago. Junior Member Posts: 69 Join Date: 8/14/12 Recent Posts
    Hi,
    I would like to pick this topic up since I am about to make migration plans for Liferay 7.

    I have a couple of productive portles using some J2EE technologies and now I found myself confronted with
    a series of NullPointerExceptions.

    My @Stateless and @Statefull beans don't get initialized the @Postcontruct methods don't run and there is no EntityManager by using @PersistenceContext.

    Is it really necessary to hack the entire system, as Daniel did or are you guys planning to support this in the future?

    best regards
    Martin
    Martin Jonik, modified 7 Years ago. Junior Member Posts: 69 Join Date: 8/14/12 Recent Posts

    Hi Daniel,

    did you get CDI running with your solution?

    I tried adding the WeldCrossContextFilter but it does not work.

    Getting the typical exception:

    Caused by: java.lang.IllegalStateException: Singleton not set for STATIC_INSTANCE =&gt; []<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.weld.bootstrap.api.helpers.RegistrySingletonProvider$RegistrySingleton.get(RegistrySingletonProvider.java:28)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.weld.Container.instance(Container.java:55)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.as.weld.WeldProvider.getCDI(WeldProvider.java:61)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at javax.enterprise.inject.spi.CDI.current(CDI.java:60)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.weld.servlet.WeldInitialListener.contextInitialized(WeldInitialListener.java:94)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.weld.servlet.api.helpers.ForwardingServletListener.contextInitialized(ForwardingServletListener.java:34)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.jboss.weld.environment.servlet.EnhancedListener.onStartup(EnhancedListener.java:65)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:184)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... 8 more
     

    [EDIT]

    The solution was to add the Weld Subsystem in standalone.xml or run the standalone-full.xml profile.
    When I installed the jsf-cdi-applicant sample portlet via Liferay's Osgi method, CDI functionality worked without having this subsystem enabled, but for the J2EE deployment I had to enable it.
    It was also necessary to but the Weld-Listener and WeldCrossContextFilter into the web.xml.