https://forums.alfresco.com/en/viewtopic.php?f=34&t=22202
https://forums.alfresco.com/en/viewtopic.php?f=34&t=14595&start=0&st=0&sk=t&sd=a
https://forums.alfresco.com/en/viewtopic.php?f=53&t=42238
https://forums.alfresco.com/en/viewtopic.php?t=8111
https://forums.alfresco.com/en/viewtopic.php?f=9&t=24759
https://forums.alfresco.com/en/viewtopic.php?f=3&t=42011
And finally this comment which was key for me:
https://forums.alfresco.com/en/viewtopic.php?f=48&t=40028#p117384
It essentially says to extend or create your own email action because the model in the default one is rather limited.
We have a need to use templates that are outside the context of the repository, which the default email action (in the enterprise version) does not handle. Since we already have rolled our own email handler (based off the community version with my own tweaks here and there), I thought I would customize it a little further to enable link generation.
My first thought was to use Java's InetAddress to get everything I needed; however, that would've proved difficult for obtaining the port; I would have had to scan each port to figure out which one the application is using. So I opted for the config route. Alfresco actually already provides us with the properties needed in alfresco-global.properties. The properties are:
... # # URL Generation Parameters (The ${localname} token is replaced by the local server name) #------------- #alfresco.context=alfresco #alfresco.host=${localname} #alfresco.port=8080 #alfresco.protocol=http # #share.context=share #share.host=alfrescodevsvr #share.port=8080 #share.protocol=http ...
Depending on your setup, you may have need to use both the alfresco.* properties and share.* properties. You'll probably want to account for both if you have the Alfresco repository and Share on two separate servers and/or need to generate links for both Alfresco Explorer and Alfresco Share interfaces. We only want to provide a link to the Share interface and both Alfresco and Share will reside on the same server, so we will only use one set of these properties to generate one link.
So in our mail action, I added these properties and setters:
... private String serverProtocol; private String serverName; private String serverPort; ... public void setServerProtocol( String serverProtocol ) { this.serverProtocol = serverProtocol; } public void setServerName( String serverName ) { this.serverName = serverName; } public void setServerPort( String serverPort ) { this.serverPort = serverPort; } ...
I originally was going to inject the entire properties object (alfresco-global: https://forums.alfresco.com/en/viewtopic.php?f=4&t=41823) but later found out I can inject the individual properties I want via config. This is more flexible in our case as it allows us to choose whether we want to use either the alfresco.* properties, the share.* properties, or some other value. Here is what the spring bean config looks like to inject values into these variables:
...... ...${share.protocol} ${share.host} ... ${share.port}
Be sure to uncomment whatever properties you decide to use in the alfresco-global.properties file. As you see above, I chose to use the Share properties, as that is what we are going to generate a link for.
Next, be sure your class implements InitializingBean, which provides us with the function afterPropertiesSet().
public class MyCompanyMailAction extends ActionExecuterAbstractBase implements InitializingBean {
We generate the server path in this function once to save on performance, and because the config can only be updated on a restart. Here is how I implemented it:
... private String serverPath = null; ... @Override public void afterPropertiesSet() throws Exception { ... StringBuilder serverPathBuilder = new StringBuilder(); serverPathBuilder.append( ( serverProtocol != null && !serverProtocol.startsWith( "${" ) && !serverProtocol.endsWith( "}" ) ) ? serverProtocol : "http" ); serverPathBuilder.append( "://" ); if ( serverName != null && !serverName.startsWith( "${" ) && !serverName.endsWith( "}" ) ) { serverPathBuilder.append( serverName ); } else { InetAddress localHost = InetAddress.getLocalHost(); serverPathBuilder.append( localHost.getCanonicalHostName() ); } serverPathBuilder.append( ':' ); serverPathBuilder.append( ( serverPort != null && !serverPort.startsWith( "${" ) && !serverPort.endsWith( "}" ) ) ? serverPort : "8080" ); serverPath = serverPathBuilder.toString(); if ( log.isDebugEnabled() ) log.debug( "Server path: " + serverPath ); } ...
I had an issue where one of the properties did not get transposed with the actual value. This occurred when the properties were not uncommented in the alfresco-global.properties file, so the injected text was literally ${share.port} instead of the port number for example. I solved that by checking for the start and end curly braces for each property:
!serverPort.startsWith( "${" ) && !serverPort.endsWith( "}" )
I wanted a default configuration in case none was provided (ie commented out), so in the code I attempt to get the host name via an InetAddress if the config is not available. The other two properties, serverProtocol and serverPort, I default those to http and 8080 as those are the most common and those values are a little harder to detect efficiently and accurately.
Next, we need to inject the serverPath into the model to be use in the template. To do this, I made a separate function to generate the model and insert whatever default values I need into it.
... private Map<String, Object> createEmailTemplateModel( NodeRef ref, Map<String, Object> suppliedModel, NodeRef fromPerson ) { Map<String, Object> model = new HashMap<String, Object>( 8, 1.0f ); ... if ( serverPath != null ) { model.put( "serverPath", serverPath ); } ... return model; } ...
Now the variable is ready to be used within a template for example:
... ...
As you can see above, this generates a link to a task through the Share interface using the property taskId that I also put into the model (this is actually done through a parameter on the action where I supply a custom model to be merged with the default model). If you wish to see the full source let me know, I will see what I can do.