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: LR7 Custom email notification in Web Form portlet
Template
I found examples for overwrite jsp in portlets using fragments but, the code I need to change is in a .soy file inside the portlet resources . How can I customize this?
Thanks
You can, however, create your own DDLFormEmailNotificationSender and register with a higher service ranking. That file has the reference to the form_entry_add_body.soy file, so you can change to point at your own file with your override that is part of your module.
But, since the DDLFormEmailNotificationSender is in a private package, you will likely need to use my blog https://web.liferay.com/web/user.26526/blog/-/blogs/fixing-module-package-access-modifiers to export the com.liferay.dynamic.data.lists.form.web.internal.notification package.
09:21:08,351 ERROR [Refresh Thread: Equinox Container: f0ced4ed-ab38-0018-12ea-b6d5253daf22][com_liferay_dynamic_data_lists_form_web:97] [com.liferay.dynamic.data.lists.form.web.internal.notification.DDLFormEmailNotificationSender] Cannot register Component
org.osgi.service.component.ComponentException: The component name 'com.liferay.dynamic.data.lists.form.web.internal.notification.DDLFormEmailNotificationSender' has already been registered by Bundle 144 (com.liferay.dynamic.data.lists.form.web) as Component of Class com.liferay.dynamic.data.lists.form.web.internal.notification.DDLFormEmailNotificationSender
I have a feeling that it might have to do with the fact that DDLFormEmailNotificationSender is a singleton, but can't find confirmation of that.
I've tried setting the name of my CustomDDLFormEmailNotificationSender component explicitly, but that doesn't help either.
To replace components, you need to implement the necessary service but use a higher service ranking so OSGi will want to use your service vs the original.
Hmm, I did use the same package name, but changing that didn't solve the problem. And my class name was already different (I had prefixed the original name with the word Custom).
package finalist.form.mailer;
import com.liferay.dynamic.data.lists.form.web.internal.notification.DDLFormEmailNotificationSender;
import com.liferay.dynamic.data.lists.model.DDLRecord;
import com.liferay.dynamic.data.lists.model.DDLRecordSet;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.template.Template;
import com.liferay.portal.kernel.template.TemplateConstants;
import com.liferay.portal.kernel.template.TemplateManagerUtil;
import com.liferay.portal.kernel.util.Portal;
import java.lang.reflect.Field;
import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(immediate = true,
service = DDLFormEmailNotificationSender.class,
name = "CustomDDLFormEmailNotificationSender",
property = {"service.ranking:Integer=100"})
public class CustomDDLFormEmailNotificationSender extends DDLFormEmailNotificationSender {
private static final String _TEMPLATE_PATH =
"/META-INF/resources/custom-mailtemplate.ftl";
protected Template createTemplate(
PortletRequest portletRequest, DDLRecordSet recordSet,
DDLRecord record)
throws PortalException {
Template template = TemplateManagerUtil.getTemplate(
TemplateConstants.LANG_TYPE_FTL,
getTemplateResource(_TEMPLATE_PATH), false);
populateParameters(template, portletRequest, recordSet, record);
return template;
}
@Reference(unbind = "-")
protected void setPortal(Portal portal) {
update("_portal", portal);
}
protected void update(final String fieldName, final Object value) {
try {
Field f = getClass().getSuperclass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(this, value);
} catch (IllegalAccessException e) {
LOG.error("Error updating " + fieldName, e);
} catch (NoSuchFieldException e) {
LOG.error("Error updating " + fieldName, e);
}
}
private static final Log LOG = LogFactoryUtil.getLog(CustomDDLFormEmailNotificationSender.class);
}
Bundle-Name: finalist-form-mailer
Bundle-SymbolicName: finalist.form.mailer
Bundle-Version: 1.0.0
Fragment-Host: com.liferay.dynamic.data.lists.form.web;bundle-version="[1.0.0, 2.0.0]"
Export-Package: com.liferay.dynamic.data.lists.form.web.constants,\
com.liferay.dynamic.data.lists.form.web.internal.notification,\
finalist.form.mailer;
Liferay-Releng-Module-Group-Description:
Liferay-Releng-Module-Group-Title: Dynamic Data Lists
-dsannotations-options: inherit
First the service declaration must match; using your own service means that only components that @Reference it are going to get it injected.
Second, the fragment bundle can introduce new classes, but it doesn't have a startable context of its own. Normally you'd have to put your component overrides into a separate bundle from the fragment bundle so they start and register correctly.
Are you able to make this working?
I am not able to ovevrride DDLFormEmailNotificationSender class using approach mentioned by David in the blog.
I am not able to ovevrride DDLFormEmailNotificationSender class using approach mentioned by David in the blog.
You should end up with two bundles:
- A fragment bundle. This bundle basically just has a bnd.bnd file, mostly copied from the original, but with the additional Export-Package directive addition.
- An implementation bundle. This bundle has your class which extends the original but returns a different soy template which is also in this bundle.
If you tried this, which part isn't working?
My goal is to add file selction in web-form and attach that file with email notification. I have already created a custom form field to support file selection but getting error for file attacment customization.
I have 2 bundles;
1. Fragment of dynamc-data-list-form-web with and one jsp file (display/view.jsp) to support multipart data and bnd.bnd.
bnd.bnd file detail;
Bundle-Name: dynamc-data-list-form-web-fragment
Bundle-SymbolicName: dynamc.data.list.form.web.fragment
Bundle-Version: 1.1.17
Fragment-Host: com.liferay.dynamic.data.lists.form.web;bundle-version="[1.0.0,2.0.0)"
Export-Package: \
com.liferay.dynamic.data.lists.form.web.constants,\
com.liferay.dynamic.data.lists.form.web.internal.notification\
Liferay-JS-Config: /META-INF/resources/admin/js/config.js
Liferay-Releng-Module-Group-Description:
Liferay-Releng-Module-Group-Title: Dynamic Data Lists
Web-ContextPath: /dynamic-data-lists-form-web
-dsannotations-options: inherit
2. Module activator class with custom DDLFormEmailNotificationSender class as below
/**
*
*/
package custom.web.form.portlet.notification;
import java.lang.reflect.Field;
import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import com.liferay.dynamic.data.lists.form.web.notification.DDLFormEmailNotificationSender;
import com.liferay.dynamic.data.lists.model.DDLRecord;
import com.liferay.dynamic.data.mapping.form.field.type.DDMFormFieldTypeServicesTracker;
import com.liferay.mail.kernel.service.MailService;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.service.UserLocalService;
import com.liferay.portal.kernel.util.Portal;
/**
* Override this class to add attachment to email
*
* @author diptivaghasia
*
*/
@Component(immediate=true,
property={"service.ranking:Integer=100"},
service=DDLFormEmailNotificationSender.class
)
public class CustomDDLFormEmailNotificationSender extends DDLFormEmailNotificationSender{
@Override
public void sendEmailNotification(PortletRequest portletRequest, DDLRecord record) {
// TODO Auto-generated method stub
_log.info("sendEmailNotification");
super.sendEmailNotification(portletRequest, record);
}
@Reference(unbind = "-")
protected void setDDMFormFieldTypeServicesTracker(
DDMFormFieldTypeServicesTracker ddmFormFieldTypeServicesTracker) {
update("_ddmFormFieldTypeServicesTracker",ddmFormFieldTypeServicesTracker);
}
@Reference(unbind = "-")
protected void setMailService(MailService mailService) {
update("_mailService", mailService);
}
@Reference(unbind = "-")
protected void setUserLocalService(UserLocalService userLocalService) {
update("_userLocalService", userLocalService);
}
@Reference(unbind = "-")
protected void setPortal(Portal portal) {
update("_portal", portal);
}
protected void update(final String fieldName, final Object value) {
try {
Field f = getClass().getSuperclass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(this, value);
} catch (IllegalAccessException e) {
_log.error("Error updating " + fieldName, e);
} catch (NoSuchFieldException e) {
_log.error("Error updating " + fieldName, e);
}
}
private static final Log _log = LogFactoryUtil.getLog(CustomDDLFormEmailNotificationSender.class);
}
problem with this class is i can not find com.liferay.dynamic.data.lists.form.web.internal.notification package to import and i think this is the problem. because when i deploy this package i am getting DDLFormEmailNotificationSender NoClassDefFoundError error.
This is my gradle file of the custom bundle i have a created for the custom DDLFormEmailNotificationSender.
dependencies {
compileOnly group: "org.osgi", name: "org.osgi.core", version: "6.0.0"
compile group: "org.osgi", name:"org.osgi.service.component.annotations", version:"1.3.0"
compile group: "com.liferay", name:"com.liferay.dynamic.data.lists.api", version: "1.0.0"
compileOnly group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
compile group: "com.liferay.portal", name:"com.liferay.portal.impl", version:"1.0.1"
compile group: "com.liferay.portal", name:"com.liferay.portal.kernel", version:"1.0.3"
compile group: "com.liferay", name: "com.liferay.dynamic.data.lists.form.web", version:"1.0.3"
compile group: "com.liferay", name:"com.liferay.dynamic.data.mapping.form.field.type", version:"2.0.0"
}
Can you please tell me what is wrong with my code?
Thanks for the help.
problem with this class is i can not find com.liferay.dynamic.data.lists.form.web.internal.notification package to import and i think this is the problem. because when i deploy this package i am getting DDLFormEmailNotificationSender NoClassDefFoundError error.
Your class doesn't reference com.liferay.dynamic.data.lists.form.web.internal.notification.DDLFormEmailNotificationSender, it is extending com.liferay.dynamic.data.lists.form.web.notification.DDLFormEmailNotificationSender which doesn't exist in later versions of the com.liferay.dynamic.data.lists.form.web bundle.
I think you originally were extending from one of the older versions of the bundle that had that c.l.d.d.l.f.web.notification package, but the newer versions do not have that legacy package anymore.
I am using liferay 7 GA5 CE.
I have referenced latest version com.liferay.dynamic.data.lists.form.web and this error is gone, but still it's executing original code of DDLFormEmailNotificationSender class.
Do you know if it is executing both, or just the old one?
Just older one is being executing.
Also try the scr:list and verify that all services are active.
I am also facing same. Have you resolved.
Please share. Thanks in advance.
Milind Jain:Hello, I am also facing same. Have you resolved. Please share. Thanks in advance.
No I could not solve this way..
Dipti Ranparia:Milind Jain:Hello, I am also facing same. Have you resolved. Please share. Thanks in advance.
No I could not solve this way..
Hi Dipti,
We implemented the same customization - adding file upload capability to web form and sending the same in email as attachment.
We did follow the official documentation to achieve this - https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-0/creating-form-field-types
Did you already tried the steps mentioned in the official documentation?
Following are the steps -
1. Implement DDMFORMFIELDTYPE Component to create new field type
2. Create Fragment for com.liferay.dynamic.data.lists.form.web to update view.jsp to add enctype="multipart/form-data" capability to form
3. Overriding Action Command to provide your own customization - (https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-0/overriding-mvc-commands)
@Component(immediate = true, property =
{"javax.portlet.name=" +
DDLFormPortletKeys.DYNAMIC_DATA_LISTS_FORM,<br>
"mvc.command.name=addRecord",<br>
"service.ranking:Integer=100"}, service = MVCActionCommand.class)
Hope this helps!!
Regards,
Harish
Has anyone successfully written these bundles to enable us to overwrite the default soy template for Forms application?
We are struggling and it would be nice if there was a version we could adopt.
I am amazed this still isn't in the core product capability, my content administrators are waiting on development to enable changing the styles in the email...
We have the build working but not getting deployed now on DXP 7.0
In 7.2, this is what we did to achieve it:
1. Created a bundle to add a custom 'email template' field in the form settings. For this, we override the
DDMFormInstanceSettings.java
interface and added our custom form setting. This was done to make the template text configurable on per form basis. If this is not your requirement, and you just want to always use a fixed custom email template, then creating this module can be skipped altogether. Note that this module needs to go to /osgi/marketplace/override folder as we are making changes to what is provided by its related lpkg file. Check https://portal.liferay.dev/docs/7-2/customization/-/knowledge_base/c/overriding-lpkg-files2. Secondly, we created a hook to create override Liferay's
DDMFormEmailNotificationSender.java
with our own custom class and registered it with a higher service ranking. Within this module we also kept a reference to the form_entry_add_body.soy template but didn't make any changes to it because we created our own form setting for custom email template per form. So we wrote our own soy file to fetch the email template from form setting (if its configured) and added it the soy file on-the-fly. Again, if you want a fixed custom template always, you don't need to create this extra soy file, and just modify the form_entry_add_body.soy
as per your need.3. Finally, but most importantly, the
DDMFormEmailNotificationSender.java
resides in a private package: com.liferay.dynamic.data.mapping.internal.notification
, therefore to be able to override it with our custom implementation, we needed it be exposed/available to be overridden. To achieve this, we simply created a fragment module to export that package via bnd :Export-Package: com.liferay.dynamic.data.mapping.internal.notification
And that's it! Hope you'll be able to achieve this in a similar way in 7.2/7.0 keeping in mind the names of the related classes and the packages in which they reside.
Can you share your code?
Powered by Liferay™