Here we will walk you through the process of setting up error reporting
specifically for portlet errors, which are among the most common issues
encountered in Liferay. To achieve this, we'll make modifications to the
portlet_error.jsp file. Since this file is part of the portal core, the
best practice for customization is through the CustomJspBag
module.
Below is a concise walkthrough on setting up a custom JSP bag to accomplish
this task.
1. In your module, create a class that implements CustomJspBag.
@Component(
immediate = true,
property = {
"context.id=StockfishCustomJspBag", "context.name=Stockfish Custom JSP Bag",
"service.ranking:Integer=100"
}
)
public class StockfishCustomJspBag implements CustomJspBag {
}
2. Implement the getCustomJspDir method to return the folder path in
your module’s JAR where the JSPs reside.
@Override
public String getCustomJspDir() {
return "META-INF/jsps/";
}
@Override
public boolean isCustomJspGlobal() {
return true;
}
3. Create an activate method and the following fields. The method adds the URL paths of all your custom JSPs to a list when the module is activated.
@Activate
protected void activate(BundleContext bundleContext) {
_bundle = bundleContext.getBundle();
_customJsps = new ArrayList<>();
Enumeration<URL> entries = _bundle.findEntries(
getCustomJspDir(), "*.jsp", true);
while (entries.hasMoreElements()) {
URL url = entries.nextElement();
_customJsps.add(url.getPath());
}
}
@Override
public List getCustomJsps() {
return _customJsps;
}
private Bundle _bundle;
private List _customJsps;
4. Implement the getURLContainer method to return a com.liferay.portal.kernel.url.URLContainer.
@Override
public URLContainer getURLContainer() {
return _urlContainer;
}
private final URLContainer _urlContainer = new URLContainer() {
@Override
public URL getResource(String name) {
return _bundle.getEntry(name);
}
@Override
public Set<String> getResources(String path) {
Set<String> paths = new HashSet<>();
for (String entry : _customJsps) {
if (entry.startsWith(path)) {
paths.add(entry);
}
}
return paths;
}
};
Once we've integrated the CustomJspBag for the portlet_error.jsp, our module structure takes on a new configuration.
Stockfish-custom-jsp-bag
└── src
├── java
│ └── com.stockfish.custom.jsp.bag
│ └── StockfishCustomJspBag.java
└── resources
├── META-INF
└── jsp
└── html
└── portal
└── portlet_error.jsp
Whenever an error occurs in the Portlet, the system will trigger email notifications to specific users. To implement this feature, we must set up a system configuration to gather users' email addresses, allowing us to send them notifications in case of errors.
To achieve this, we've defined an EmailNotificationsConfiguration class, which manages these settings.
@ExtendedObjectClassDefinition(
category = "stockfish",
scope = ExtendedObjectClassDefinition.Scope.SYSTEM
)
@Meta.OCD(
id = "com.stockfish.test.configuration.EmailNotificationsConfiguration",
localization = "content/Language",
name = "sending-email-for-not-displaying-mvcportlet"
)
public interface EmailNotificationsConfiguration {
@Meta.AD(deflt = "", name = "Email-Address", required = false)
public String emailAddress();
}
@Component(service = ConfigurationCategory.class)
public class SystemConfigurationCategory implements ConfigurationCategory {
@Override
public String getCategoryIcon() {
return "plug";
}
@Override
public String getCategoryKey() {
return "stockfish";
}
@Override
public String getCategorySection() {
return "other";
}
}
Created system configuration is look like below:
We can utilize both RestAPI and MVCResourceCommand to send email notifications. In this context, we'll focus on using MVCResourceCommand for sending email notifications.
Now we are going to create a class that implements MVCResouceCommand. In this class, we'll write code to retrieve email addresses from the system configuration and send email notifications to the specified users whenever an error occurs in the Portlet.
@Component(
immediate = true,
configurationPid ="com.stockfish.test.configuration.EmailNotificationsConfiguration",
property = {
"javax.portlet.name=" + TestPortletKeys.TEST,
"mvc.command.name=sendingEmail"
},
service = MVCResourceCommand.class
)
public class SendingEmailMVCResource implements MVCResourceCommand {
@Override
public boolean serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws PortletException {
// ToDo: write a code for sending an email
}
}
We'll trigger this resourceCommand whenever an error is detected.
To accomplish this, we'll invoke the resourceCommand when the portlet_error.jsp is loaded, using the resource URL as demonstrated below.
<script>
$(document).ready(function() {
var basePortletURL = window.location.href;
var resourceURL = Liferay.Util.PortletURL.createResourceURL(
basePortletURL,
{
'p_p_id': 'com_stockfish_test_TestPortlet',
'p_p_resource_id': 'sendingEmail',
}
);
$.ajax({
url: resourceURL,
type: 'POST',
success: function(data) {
console.log("Export URL called successfully");
},
error: function(xhr, status, error) {
console.error("Error calling export URL: " + error);
}
});
});
<script>
That's it !! We've just completed the integration of email notifications to alert us when portlet errors occur. This addition will help us stay on top of issues and respond quickly, improving overall system reliability. With these notifications in place, our response time to portlet errors will be much faster.
For comprehensive business solutions and in-depth insights into Error reporting framework, connect with us at info@stockfish.app to unlock the full potential of your digital platform.