Search code examples
javaliferayliferay-7

How to work with Liferay internal code in portlets?


Previously I asked a Question on how to access session data that was set by liferays internal OIDC process. In the end I accessed the token using java reflection but I cannot believe that this is the right or only way to do it.

I added the following dependencies hoping I would then be able to just directly use the OpenIdConnectSessionImpl but this way I cannot add the portlet to my liferay.

compileOnly 'com.liferay:com.liferay.portal.security.sso.openid.connect.impl'
compileOnly group: 'com.nimbusds', name: 'oauth2-oidc-sdk', version: '5.17.1'

This is the code I use:

Object oidcSession = httpSession.getAttribute("OPEN_ID_CONNECT_SESSION");

if (oidcSession instanceof OpenIdConnectSessionImpl) {
  OpenIdConnectSessionImpl openIdConnectSessionImpl = (OpenIdConnectSessionImpl) oidcSession;

  LOG.info(openIdConnectSessionImpl.getUserInfo().toJSONObject().toString(new JSONStyle(4)));
} else {
  LOG.info("What is this.");
}

Getting the token from oidcSession using reflection works but not using the actual Class.


Solution

  • The beauty of Liferay's modularity through OSGi is that you can have access to everything that's designed for your access (e.g. exported) and nothing that's explicitly not exported. Classes ending in Impl typically are among the nonexported classes.

    You can still create access, but you'll know explicitly that you're going way beyond the published API, and you make yourself dependent on the implementation. Guess who's also changing the implementation, without taking care of anybody else? The upstream project. Liferay's developers are working hard to keep an API stable, but it's their business to change their implementation.

    If you decide that you'll need access to the implementation: You're welcome, open up those modules. Just be aware that every single future (minor) upgrade might change an aspect of the implementation that you're relying on. You're willingly accepting a high maintenance burden for the future. For some features this is fine, and you may be willing to pay that price. Other features might not justify this price. Choose wisely.

    There is no general answer to this question, just a bunch of rules of thumb:

    • Re-phrase the problem, to search for an alternative solution. Sometimes a solution that takes longer for its first shot is a lot easier to maintain in the long run
    • Make the cost of an intrusive change visible to the business stakeholders. I've seen many feature requests vanish or change significantly, when they had a price tag
    • Search for alternative implementations along an API
    • Describe your (business) problem (not the solution) to the Liferay developers: They may introduce an extension point in the future, so that you can replace your intrusive change of a module's implementation with an API-based module in the next version.