Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: How I can inject dependency of classes in an extension module?
Hello, I am developing a new extension for the Login module. I was able to modify the login.jsp page and change some texts (a simple POC) and these changes replaced correctly the original Login page. Problem started when I tried to include more complexity...I want to add to my Login page, all the OpenId providers configured in the portal. As it is are existing modules, I added all the dependencies of the build.gradle file:dependencies {
...
compileOnly 'com.liferay:com.liferay.portal.security.sso.openid.connect.api'
compileOnly 'com.liferay:com.liferay.portal.security.sso.openid.connect.impl'
...
originalModule group: "com.liferay", name: "com.liferay.login.web"
}
After that were included all required jars to my project so there is no depency or compilation problem. Then I was able to include some classes in my new extended LoginPortlet.java.
As documentation explain, I am including the variables with @Reference annotation:
@Reference
private OpenIdConnect _openIdConnect; @Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;I am assuming that code fire Dependency Injection, so it is no needed to instatntiate manually. I am using them as follows:public class LoginPortlet extends MVCPortlet { @Reference(
target = "(&(release.bundle.symbolic.name=com.liferay.login.web)(&(release.schema.version>=1.0.0)(!(release.schema.version>=2.0.0))))",
unbind = "-"
)
protected void setRelease(Release release) {
}
@Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
List<IDP> providers = new ArrayList<IDP>();
ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
long companyId = themeDisplay.getCompanyId(); if (_openIdConnect.isEnabled(companyId)) {
Collection<String> idps = _openIdConnectProviderRegistry.getOpenIdConnectProviderNames(companyId);
Iterator<String> iterator = idps.iterator();
while (iterator.hasNext()) {
providers.add(new IDP(iterator.next()));
}
} renderRequest.setAttribute("idps", providers); super.doView(renderRequest, renderResponse);
} @Reference
private OpenIdConnect _openIdConnect; @Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;
}My problem is that at execution time it throws a NPE and I don't know the reason. In fact if I debugg the code, referenced variables _openIdConnect and _openIdConnectProviderRegistry were not autowired.Finally same happens if I try to use any class of the OpenId module in the login.jsp directly.There is anyone can help me please?Regards,Mark
...
compileOnly 'com.liferay:com.liferay.portal.security.sso.openid.connect.api'
compileOnly 'com.liferay:com.liferay.portal.security.sso.openid.connect.impl'
...
originalModule group: "com.liferay", name: "com.liferay.login.web"
}
After that were included all required jars to my project so there is no depency or compilation problem. Then I was able to include some classes in my new extended LoginPortlet.java.
As documentation explain, I am including the variables with @Reference annotation:
@Reference
private OpenIdConnect _openIdConnect; @Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;I am assuming that code fire Dependency Injection, so it is no needed to instatntiate manually. I am using them as follows:public class LoginPortlet extends MVCPortlet { @Reference(
target = "(&(release.bundle.symbolic.name=com.liferay.login.web)(&(release.schema.version>=1.0.0)(!(release.schema.version>=2.0.0))))",
unbind = "-"
)
protected void setRelease(Release release) {
}
@Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
List<IDP> providers = new ArrayList<IDP>();
ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
long companyId = themeDisplay.getCompanyId(); if (_openIdConnect.isEnabled(companyId)) {
Collection<String> idps = _openIdConnectProviderRegistry.getOpenIdConnectProviderNames(companyId);
Iterator<String> iterator = idps.iterator();
while (iterator.hasNext()) {
providers.add(new IDP(iterator.next()));
}
} renderRequest.setAttribute("idps", providers); super.doView(renderRequest, renderResponse);
} @Reference
private OpenIdConnect _openIdConnect; @Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;
}My problem is that at execution time it throws a NPE and I don't know the reason. In fact if I debugg the code, referenced variables _openIdConnect and _openIdConnectProviderRegistry were not autowired.Finally same happens if I try to use any class of the OpenId module in the login.jsp directly.There is anyone can help me please?Regards,Mark
It's missing, but is your LoginPortlet also having an @Component annotation? @Reference only works for @Components.
I'm thinking it's not. An @Component will not start unless all @Reference values are resolvable and wired in. If they were available and you had an @Component, then they would not be null. If they were not available and you had an @Component, then your component would not start. Regardless if they were available or not, if you are not an @Component you class can be instantiated and called and nothing gets "autowired" so the values would be null.
I'm thinking it's not. An @Component will not start unless all @Reference values are resolvable and wired in. If they were available and you had an @Component, then they would not be null. If they were not available and you had an @Component, then your component would not start. Regardless if they were available or not, if you are not an @Component you class can be instantiated and called and nothing gets "autowired" so the values would be null.
Hello David, in fact when the new extension files are cloned into my Extension modues I think they are created as a copy of the original ones and includes the @Component annotation.
This is my code for example,
package com.liferay.login.web.internal.portlet;
import com.liferay.login.web.IDP;
import com.liferay.login.web.constants.LoginPortletKeys;
import com.liferay.portal.kernel.model.Release;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.security.sso.openid.connect.OpenIdConnect;
import com.liferay.portal.security.sso.openid.connect.OpenIdConnectProviderRegistry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.portlet.Portlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Peter Fellwock
*/
@Component(
immediate = true,
property = {
"com.liferay.portlet.add-default-resource=true",
"com.liferay.portlet.css-class-wrapper=portlet-login",
"com.liferay.portlet.display-category=category.tools",
"com.liferay.portlet.icon=/icons/login.png",
"com.liferay.portlet.preferences-owned-by-group=true",
"com.liferay.portlet.private-request-attributes=false",
"com.liferay.portlet.private-session-attributes=false",
"com.liferay.portlet.render-weight=50",
"com.liferay.portlet.single-page-application=false",
"com.liferay.portlet.use-default-template=true",
"javax.portlet.display-name=Sign In",
"javax.portlet.expiration-cache=0",
"javax.portlet.init-param.add-process-action-success-action=false",
"javax.portlet.init-param.config-template=/configuration.jsp",
"javax.portlet.init-param.template-path=/META-INF/resources/",
"javax.portlet.init-param.view-template=/login.jsp",
"javax.portlet.name=" + LoginPortletKeys.LOGIN,
"javax.portlet.portlet-mode=text/html;config",
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=guest,power-user,user"
},
service = Portlet.class
)
public class LoginPortlet extends MVCPortlet {
@Reference(
target = "(&(release.bundle.symbolic.name=com.liferay.login.web)(&(release.schema.version>=1.0.0)(!(release.schema.version>=2.0.0))))",
unbind = "-"
)
protected void setRelease(Release release) {
}
@Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
List<IDP> providers = new ArrayList<IDP>();
ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
long companyId = themeDisplay.getCompanyId();
if (_openIdConnect.isEnabled(companyId)) {
Collection<String> idps = _openIdConnectProviderRegistry.getOpenIdConnectProviderNames(companyId);
Iterator<String> iterator = idps.iterator();
while (iterator.hasNext()) {
providers.add(new IDP(iterator.next()));
}
}
renderRequest.setAttribute("idps", providers);
super.doView(renderRequest, renderResponse);
}
@Reference
private OpenIdConnect _openIdConnect;
@Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;
}
Maybe I am missing something?
Thanks for your help.
This is my code for example,
package com.liferay.login.web.internal.portlet;
import com.liferay.login.web.IDP;
import com.liferay.login.web.constants.LoginPortletKeys;
import com.liferay.portal.kernel.model.Release;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.security.sso.openid.connect.OpenIdConnect;
import com.liferay.portal.security.sso.openid.connect.OpenIdConnectProviderRegistry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.portlet.Portlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Peter Fellwock
*/
@Component(
immediate = true,
property = {
"com.liferay.portlet.add-default-resource=true",
"com.liferay.portlet.css-class-wrapper=portlet-login",
"com.liferay.portlet.display-category=category.tools",
"com.liferay.portlet.icon=/icons/login.png",
"com.liferay.portlet.preferences-owned-by-group=true",
"com.liferay.portlet.private-request-attributes=false",
"com.liferay.portlet.private-session-attributes=false",
"com.liferay.portlet.render-weight=50",
"com.liferay.portlet.single-page-application=false",
"com.liferay.portlet.use-default-template=true",
"javax.portlet.display-name=Sign In",
"javax.portlet.expiration-cache=0",
"javax.portlet.init-param.add-process-action-success-action=false",
"javax.portlet.init-param.config-template=/configuration.jsp",
"javax.portlet.init-param.template-path=/META-INF/resources/",
"javax.portlet.init-param.view-template=/login.jsp",
"javax.portlet.name=" + LoginPortletKeys.LOGIN,
"javax.portlet.portlet-mode=text/html;config",
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=guest,power-user,user"
},
service = Portlet.class
)
public class LoginPortlet extends MVCPortlet {
@Reference(
target = "(&(release.bundle.symbolic.name=com.liferay.login.web)(&(release.schema.version>=1.0.0)(!(release.schema.version>=2.0.0))))",
unbind = "-"
)
protected void setRelease(Release release) {
}
@Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
List<IDP> providers = new ArrayList<IDP>();
ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
long companyId = themeDisplay.getCompanyId();
if (_openIdConnect.isEnabled(companyId)) {
Collection<String> idps = _openIdConnectProviderRegistry.getOpenIdConnectProviderNames(companyId);
Iterator<String> iterator = idps.iterator();
while (iterator.hasNext()) {
providers.add(new IDP(iterator.next()));
}
}
renderRequest.setAttribute("idps", providers);
super.doView(renderRequest, renderResponse);
}
@Reference
private OpenIdConnect _openIdConnect;
@Reference
private OpenIdConnectProviderRegistry<?, ?> _openIdConnectProviderRegistry;
}
Maybe I am missing something?
Thanks for your help.
Additionally, if I test a similar code inside another Portlet Module it works fine. I don't know if it could be related to the fact that extension modules are hooks for existing ones and when they are deployed some initializations or dependency injections don't happens.
This looks right to me. Have you tried purging osgi/state?
Hello David, actually I did, also I had clean all temporary files, etc but same results. Dependency injections are ok in other modules but still failling in EXT. I can´t fin the reason...
Hello Mark, I am facing the same issue.. did u get any solution for this?
Hello Upender, unfortunetly nop. If you can fix it please share, please!