Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #47

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Mobe91
Copy link
Contributor

@Mobe91 Mobe91 commented Dec 16, 2022

No description provided.

@Mobe91 Mobe91 requested a review from beikov December 16, 2022 18:12
Comment on lines 53 to 62
ServiceProvider serviceProvider = configurationSource.getPropertyOrDefault(SERVICE_PROVIDER_PROPERTY, ServiceProvider.class, val -> null, (serviceType) -> null);
this.templateEngine = serviceProvider.getService(ITemplateEngine.class).orElse(new TemplateEngine());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like NPEs are possible. Please throw some meaningful exception i.e. Required ServiceProvider is not available in configuration source. Alternatively, try to handle the null service provider maybe?

Comment on lines 104 to 89
private F from;
private Long fromId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should remove the two fields and just leave a public abstract AbstractFromEmail getFrom() for a user to implement. AFAICS, you also don't need the type parameter. Users can covariantly override the contract.

* The parameter name for the subject template processor key which is a plain {@link String}.
* The value refers to a template processor key.
*/
public static final String SUBJECT_TEMPLATE_PROCESSOR_KEY_PARAMETER = "subjectTemplateProcessorKey";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a horrible pattern. People will usually only use a single template engine. So storing the template engine name for every email is just useless. The template engine should be resolved based on some resolver the user can override, which may receive access to the notification itself, so that the user can put the template engine name somehwere in case it isn't always the same.

We have to rethink this part a bit. We need something like this:

interface TemplateProcessorFactoryResolver {
    TemplateProcessorFactory<T> resolveTemplateProcessorFactory(TemplateContext context, Class<T> resultType, Notification<?> notification, ConfigurationSource confiurationSource, ServiceProvider serviceProvider);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this interface is not needed as the user could just create a custom TemplateProcessorFactory that performs some kind of delegation. So maybe let's reduce the discussion to only allowing a single TemplateProcessorFactory per notification.

The issue is a different one: It must be possible to use different template processors for different parts of the same notification. Not sure how this interface would make this possible? If you only allow a single TemplateProcessorFactory then the caller must somehow provide information for what part of the notification the template processor is being created. I don't know how to do this in a generic fashion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The processor is based on the template name, no? And that one is configured per notification part. So if we resolve the TemplateProcessorFactory (representing the template engine) once and then call createTemplateProcessor for every notification part with the respective notification parts template name, then we should have proper TemplateProcessor objects to create the final parts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we can do it that way but it basically shifts the responsibility to the user having to implement custom TemplateProcessorFactory where delegation is performed based on the templateName.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the user of blaze-notify should at most configure a base path where to find templates on the class path, but even for that I would suggest we use some sane default like e.g. templates/

Comment on lines 243 to 247
if (TemplateProcessor.TEMPLATE_NAME_PROPERTY.equals(key)) {
return templateName;
} else if (TemplateProcessor.SERVICE_PROVIDER_PROPERTY.equals(key)) {
return serviceProvider;
}
Copy link
Member

@beikov beikov Dec 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two parameters should be part of the TemplateProcessorFactory#createTemplateProcessor method so that we don't have to construct a lambda every time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EmailNotificationMessageResolver is cached in com.blazebit.notify.NotificationJobContext.Builder.DefaultNotificationJobContext#getNotificationMessageResolver(java.lang.Class<T>, com.blazebit.job.ConfigurationSource) so this code should not be executed every time.
Also, how do you suggest to pass these data items into the TemplateProcessorFactory?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just change the createTemplateProcessor method to accept these two additional parameters, then you don't need the lambda anymore.

public class EmailNotification extends AbstractEmailNotification<Long> implements ConfigurationSourceProvider {

private static final long serialVersionUID = 1L;
public interface ServiceProvider {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a new ServiceProvider interface and can't just use the existing one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing one is part of blaze-job-core-api. So I would have had to introduce a dependency to blaze-job in order to reuse this class which I thought doesn't make sense (why would the template module depend on the job module).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template stuff is just an integration aspect of blaze-notify which already depends on the job module, so it's fine to add another dependency here IMO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we duplicate com.blazebit.notify.template.api.ConfigurationSource then instead of just using com.blazebit.job.ConfigurationSource?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A mistake I guess.

@Mobe91 Mobe91 force-pushed the various_improvements branch 2 times, most recently from 2fa1190 to cc204e5 Compare December 19, 2022 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants