Advanced Share Customization (part 1)

cancel
Showing results for 
Search instead for 
Did you mean: 

Advanced Share Customization (part 1)

ddraper
Intermediate II
0 31 15.1K

Introduction

At DevCon in San Diego last week I got asked a number of times how possible it would be to either radically customize Share or add entirely new pages to it. I got the opportunity to demonstrate how easy this was and realised that it would probably be a good basis for a blog. In this first post I'm going to demonstrate how to add a new page to Alfresco Share (and have it protected by the standard authentication mechanism) and make it the application landing page. In the next post I'll show how to replace the default login form and provide a link to a stripped down document library page.

Step 1: Add a new page

Adding a new page into Alfresco Share is almost trivially easy and can be done in a minimum of three files:

    • A Page definition file
    • A Template-Instance definition file
    • A FreeMarker template file


Stripping these files to the bare minimum content these should look as follows:

Page definition ('home-page.xml')

This file defines the page to name (which is the file name) and a mapping to a Template-Instance that contains the content. It also defines the level of authentication required to view the page.

<page>
   <template-instance>home-page</template-instance>
   <authentication>user</authentication>
</page>

 

Template-Instance definition ('home-page.xml')

This creates a mapping to the actual FreeMarker template that contains the content for the page.

<template-instance>
   <template-type>blog/demo/home-page</template-type>
</template-instance>‍‍‍‍‍‍

FreeMarker template file ('home-page.ftl')

This contains the actual page content. The example shown here is trivial but this could also contain regions for binding Spring Surf components if required.

<html>
   <head>
      <title>Blog Application</title>
   </head>
   <body>
      Welcome To Extreme Share Customization!
   </body>
</html>


The files should be build into a JAR file in the following structure:

    • /alfresco/site-data/pages/home-page.xml
    • /alfresco/site-data/template-instances/home-page.xml
    • /alfresco/templates/blog/demo/home-page.ftl


Assuming that you are running on Tomcat, copy the JAR file into either 'webapps/share/WEB-INF/lib' or '<tomcat-home>/shared/lib'. If you're not running on Tomcat then you'll need to adjust the location to suit your specific web server. You'll need to ensure that your Tomcat server is correctly configured if you wish to use '<tomcat-home>/shared/lib' and you should be aware that the page you have defined will be available to all Spring Surf based applications running on that web server!!

Restart your web server and then open the following location in your browser to 'http://localhost:8080/share/page/home-page' (adjust the port as necessary for your application configuration!). You will be prompted with the standard Alfresco Share login screen - this is because the page has specified and authentication level of 'user'. If you want only your administrator to access the page then you could set this as 'admin' and if you want the page to be public you could set it to 'none'.

The key thing to note here is that although your page effectively belongs to the Alfresco Share application your FreeMarker template can contain any HTML/JavaScript/CSS that you wish - you are not tied into using YUI2 as is used in the implementation of Alfresco Share - should you wish to write a page a page in JQuery or Dojo or pure HTML  (or anything else) then you are quite at liberty to do so.

Also, as well as being able to re-use the standard Alfresco Share authentication mechanism you are also able to easily access all the WebScripts available on both the Web and Repository tiers. This means you can easily build your own UI around existing Alfresco functionality.

When bringing in resources (such as images, JavaScript and CSS files) it's important to remember that you should place them under the META-INF folder in your JAR and use the '/res' prefix on the requests to access them (e.g. request the file 'META-INF/blog/demo/example.css' using the URL '/share/res/blog/demo/example.css'.

Step 2: Make the new page the landing page

PLEASE NOTE: Whilst writing this section I discovered a couple of bugs in the Spring Surf code which have been fixed. In order to make sure this example works you will either need to build the latest version of Alfresco or wait for version 4.0.c

Spring Surf supports the notion of a default page which is defined in the site configuration (that's site as in 'Web Site', rather than the Alfresco Share concept of site!). By default the default page is the 'site-index.jsp' which works out and redirects to the authenticated users dashboard page. A the site default page will be rendered when a request is mapped to the Spring MVC RequestDispatcher (which by default is at '/page' and '/p') but no page is included in the request (e.g. '/share/page'). This is also configured as the 'welcome-file' in the Share 'web.xml' file.

In order to change the landing page for the application you can simply override the default site configuration for Alfresco Share. The site configuration used is defined in 'surf.xml' and is set to 'slingshot.site.configuration' by default.

To customize Alfresco Share to use our new landing page you simply need to create a file called 'slingshot.site.configuration.xml' containing the following:

<configuration>
   <source-id>site</source-id>
   <properties>
      <root-page>home-page</root-page>
   </properties>
</configuration>


Build the file into your JAR at the following location:

    • /alfresco/web-extension/site-data/configurations


Note that the file needs to under the 'web-extension' path in order that it gets resolved before the Alfresco Share default!

After deploying your JAR file and restarting the web server you should find that when you point your browser at 'http://localhost:8080/share' you will be taken to your new page by default (after you login of course!)

31 Comments
blog_commenter
Active Member
[...] the first part of this tutorial I demonstrated how you could add a new page to Alfresco Share and have it protected by the standard [...]
blog_commenter
Active Member
Hi David,

After deploying the last jar with the overridden /alfresco/web-extension/site-data/configurations/slingshot.site.configuration file the home-page remains the user/admin/dashboard whenever I login.
Changing the filename to /alfresco/web-extension/site-data/configurations/slingshot.site.configuration.xml does not change this behaviour neither does changing it to custom-slingshot.site.configuration.xml or custom-slingshot.site.configuration and all other variants, so my guess is that the location is not correct??
Can you verify this?
I have deployed my jar file in webapps/share/WEB-INF/lib

Best regards,

Peder
ddraper
Intermediate II
Hi Peder,

You're right that the file should be called 'slingshot.site.configuration.xml' (I'll update the post - thanks for spotting that). All the blog posts are done on real code examples that I'm implemented and my version *was* working when I wrote the blog but I'm now experiencing the same issue as you. I'll investigate this and post a response when I've tracked the problem down.

Regards,
Dave
ddraper
Intermediate II
Hi Peder,

I've tracked down the reason that I was experiencing the problem (which is hopefully the same reason that you've experienced it).  I had changed the theme of Share and in doing so the default site configuration was updated with the new theme and persisted to the repository. When Surf attempts to retrieve objects it searches through a number of different locations (for example the 'alfresco/web-extension' root is searched before 'alfresco' which is how overrides typically work) but the first location searched is the remote store. This means that once the site configuration is updated and persisted you can no longer override it with a file under web-extension.

For this example this is perfectly valid since if you are customizing Share such that it has no access to the standard pages and no ability to set themes (or if you wanted to theme your custom pages then you should also customize how theme changes are persisted).

There are 2 ways in which you can resolve this issue... the brute force approach would be to clear your database and delete your content store. Alternatively you can delete the 'slingshot.site.configuration.xml' directly from the repository but to do this you will need to use the Repository client (i.e the original Alfresco client found at /alfresco rather than /share). Simply search for the file and then delete it... then your override file should take effect.

I hope this helps,

Regards,
Dave
blog_commenter
Active Member
Hi,

Firstly, Thanks very much David, this and the other tutorials here have been invaluable in getting Alfresco set up and working in the fashion we need it to. Secondly, what I actually first thought as I was starting to read these was that I would be able to make a site looking pretty much exactly the same as those already created by Share but use it as the default landing page after login. What I tried first was just to use the first XML file (the page definition) pointing at the 2 columns wide right template instance, which left me with a header bar and no actual content. I also tried copying the dashboard.xml of a site I had created in the web browser into the page definition with the same result. I have read through site-index.jsp and as I read it, it is looking for a variable - site - which, if it is set and non-zero length it uses to direct to the site in question, otherwise it directs to the user dashboard. If I read this correctly I should just have to use the slingshot site config file to set this variable to the site name I wish to be the landing page. This is what I have done so far-
1. Created a new site using an Admin user in share. I called it example, so I can access it at http://our.server.name:8080/share/page/site/example/dashboard
2. created a jar with a single file in it's structure - /alfresco/site-data/configurations/slingshot.site.configuration.xml
3. This file looks like this -

   site
  
      example
  


4. drop the jar in tomcat/shared/lib (I am not sure where it goes in JBOSS but I assume its fairly similar)
5. restart the web server

however we are still redirected to the user dashboard after SSO completes. I feel like this is related to your previous comment to Peder, as we have also added custom themes with a separate jar file (this is the only other jar deployed apart from the out of the box install). Unfortunately I wasn't able to follow the last part of your paragraph where you explain the issue - While I understand the order of prevalence with different locations to set configurations I do not understand how deleting this file will resolve an issue (When I tried removing it we still had the same problem, the only change I noticed was it changed the set theme back to default blue after the server restart).

Is there something I am missingor have I incorrectly assumed I can do this with only slingshot.site.configuration.xml and a prebuilt share site?
blog_commenter
Active Member
Oops - David - in my previous post it looks like the XML where I posted my slingshot config was stripped - the source ID field is site and the root-page field is example. it is as you have it in your original tutorial but with example where home-page was.
ddraper
Intermediate II
Hi Chris,

Firstly, thanks for the feedback - it's much appreciated!

Sorry you're having issues with this issue, I'll do what I can to help out. The reason that removing the persisted configuration file might have worked is because when you make any site modifications (such as selecting a different theme from within the Admin Console) then configuration is saved to the Alfresco Repository. Surf configuration from the Repo is always retrieved before classpath/filesystem configuration so the site configuration in your JAR file will not be used (so your root page will revert to the Share default because we are writing fresh configuration from scratch - this is something we can probably do something about though).

Since you're working on JBOSS and not Tomcat, can you confirm that other types of customization work when added to a JAR in the location that you're using? I'd just like to know that your code is definitely being picked up by Surf - this would be the obvious place to start and then we can take it from there.

Also, I've not tried any of this with SSO but I don't *think* that it should make a difference although I'll look into it.

Regards,
Dave
blog_commenter
Active Member
Hi David,

Sorry for the confusion, actually I am working on Tomcat. I can see what made you think that, when I was originally writing that it was going to be a 'This is how I solved a similar issue in case it helps anyone', I was basically sure it would work. Once the server finished restarting I realized it was not going to work and so I got rid of most of the 'this is how to do it' stuff from my steps and kept most of the post as 'this is how I attempted to do it and failed' Smiley Tongue. I missed that one in step 4 though until afterwards and couldn't edit it once I noticed.

That said, other customization types via jar do work - we only have the one other customization (a theme) but it is working. At the moment I have actually kludged my way around it for a temporary workaround, to allow me to start designing what will be the landing page - I changed site-index.jsp in /webapps/share to force a redirect to my chosen page. This works, but obviously is not a permanent solution, I know it is poor practice to change files in this location.
blog_commenter
Active Member
Oh my. I think I have realized the issue (or part of it) and it is a little embarrassingly easy. I went back into my ant directory structure to check I had pluralized configurations (which I had) and saw that I missed a level of the directory. I was putting it /alfresco/site-data/configurations/slingshot.site.configuration.xml instead of /alfresco/web-extension/site-data/configurations/slingshot.site.configuration.xml.
What's that, you specifically, in italics and with an exclamation point pointed out that the file HAS to be under the web-extension directory? Bloody end users! Smiley Tongue

Unfortunately, having deployed this, deleted the slingshot config and restarted the server, when I navigate to https://our.server:8443/share I get an Internal server 500 Error message and in catalina.out -

2012-04-27 10:32:08,635  ERROR [alfresco.web.site] [http-8443-4] org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
java.lang.NullPointerException
        at org.springframework.web.servlet.view.UrlBasedViewResolver.loadView(UrlBasedViewResolver.java:421)
        at org.springframework.web.servlet.view.AbstractCachingViewResolver.createView(AbstractCachingViewResolver.java:158)
        at org.springframework.web.servlet.view.UrlBasedViewResolver.createView(UrlBasedViewResolver.java:384)
        at org.springframework.extensions.surf.mvc.AbstractWebFrameworkViewResolver.resolveViewName(AbstractWebFrameworkViewResolver.java:366)
        at org.springframework.web.servlet.DispatcherServlet.resolveViewName(DispatcherServlet.java:1078)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1027)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.alfresco.web.site.servlet.MTAuthenticationFilter.doFilter(MTAuthenticationFilter.java:74)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.alfresco.web.site.servlet.SSOAuthenticationFilter.processType3(SSOAuthenticationFilter.java:922)
        at org.alfresco.web.site.servlet.SSOAuthenticationFilter.doFilter(SSOAuthenticationFilter.java:499)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:662)

an exception. I checked and re-checked that I had the contents of slingshot.site.configuration.xml the same as yours, apart from the root-page field itself pointing to the name of the site I created. I get the feeling this is something to do with the difference between the pages created via your method above and those created via the web browser in share. The page definition is not in the same place (as far as I can tell it is in the sites surf-config directory in the repo and called dashboard.xml instead of page-name.xml), I feel like this may be related. could this be the case?
ddraper
Intermediate II
Ok, so it looks like your site configuration changes might have taken - however, it looks like the page itself may not be correctly defined. Have you checked that you can actually reach that page manually? (i.e. at 'share/page/example' -assuming that's still the page name). If you're not able to hit the page manually then you'll need to check the configuration for it - if you can hit the page then it might be something else.

I'm a bit confused as to why the page is under the surf-config directory? Is that where you've created it - if so, is there a particularly reason for that. Again, I'd start with configuring your new page as simply as possible (i.e in the JAR or directly in your exploded WAR) and then take it from there once that bits working.

Also, could you confirm which version you're on (just because the stacktrace doesn't tally from the latest Surf libs so I'll need to work back to earlier revisions to help with this).

Regards,
Dave
blog_commenter
Active Member
Hi Dave,

It seems that Chris wants to set site dashboard as landing page and not a custom created page. That is my intention as well - to redirect user directly to existing site dashboard.

If I put just site URL Name as root-page in the slingshot.site.configuration.xml file, I'm getting the same error as Chris. But if I put site/test/dashboard as root-page I'm redirected to site dashboard but not fully successful. Somehow the name of the site is not recognized and I'm getting the following error displayed on top of the page:

An error has occured in the Share component: /share/service/components/title/collaboration-title.
It responded with a status of 500 - Internal Error.
Error Code Information: 500 - An error inside the HTTP server which prevented it from fulfilling the request.
Error Message: 03270000 Failed to process template org/alfresco/components/title/collaboration-title.get.html.ftl
Server: Alfresco Spring WebScripts - v1.0.0 (Release 958) schema 1,000
Time: Apr 27, 2012 3:07:23 PM
Click here to view full technical information on the error.
Exception: freemarker.core.InvalidReferenceException - Expression page.url.templateArgs.site is undefined on line 38, column 67 in org/alfresco/components/title/collaboration-title.get.html.ftl.
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:125)
...

And I noticed that site-dashboard link points to http://hostSmiley Tongueort/share/page/site//dashboard
Site identifier is missing. Any ideas?

Thank you,
Blaž
ddraper
Intermediate II
Hi Blaž,

The reason for this error is that accessing the root page bypasses the URI template matches page view resolver code. There are URI templates configured for Share (in 'share-config') that match to site and user dashboards (e.g. /site/{site}/dashboard) - the token that the collaboration-title WebScript is looking for is the {site} token which is set when a URL is mapped to the URI template.

Surf is not currently checking the root page for token mapping - it just assumes that if a root page is configured then it should exist so the tokens are never set and the WebScript generates an error. I'd consider this to be a bug in Surf and have actually just implemented and tested a fix.

I've raised an issue (https://issues.alfresco.com/jira/browse/ALF-13896) to address this and committed the updated Surf libs to the Alfresco Community source (so if you're just using Community then you can build the latest version of the code). If you're an Enterprise customer then I'd suggest that you raise it with support to try and get the fix merged into a 4.0.x release.

Regards,
Dave
blog_commenter
Active Member
Thanks Dave,

I'm an Enterprise customer but currently building PoC based on Community version. Eventually I'll need the same option on Enterprise as well so I'll raise it with support.

Blaž
blog_commenter
Active Member
Hi Dave,

Blaž is correct, I am trying to use an existing site dashboard. I did not choose to put the page definition under surf config, but a file called dashboard.xml and with syntax suggestive of a page definition file exists/was created by share when I made the new site dashboard. I can access the dashboard directly via URL. The version is definitely 4.0.d community.

Blaž, does the error message you get appear to users or is it just a backend message in the logs? I am sick from work today but will definitely be interested to try using site/test/dashboard tomorrow when I am back and I will let you know.

One final thing, Dave - I noticed that the bug report you filed is listed as fixed, but says fixed in version 'Odin'. Whereabouts does Odin sit in relation to current versions?

Regards,
Chris
ddraper
Intermediate II
Hi Chris,

Odin is the project name for the next major release of Alfresco. This effectively means it's fixed on the latest Community Source on the main trunk of SVN. At the moment it's not targeted for a 4.0.x Enterprise release but the fix may get merged if the support team feel it is necessary - and if not, it could still go into an Enterprise 4.0.x release as a result of any other fix targeted for 4.0.x that requires updated Spring Surf libs.

Regards,
Dave
blog_commenter
Active Member
Hi guys,

I came to the realization this morning that I was really just turning this into a far more complicated problem than it needs to be. I am glad to say that I now have an error free redirection to the dashboard page I created in 4.0d community (though I expect this would also work in Enterprise).
I followed the exact steps as David has them above, then in the home-page.ftl file I included-
meta http-equiv='REFRESH' content='0;url=https://{our.server.local}:8443/share/page/site/{mypage}/dashboard'
(enclosed with tag ends inside the html head section)
inside the with {our.server.local} and {mypage} swapped out for sane values. It's not exactly the prettiest solution but it was easy and it worked, error-free.
blog_commenter
Active Member
Hi David,

I just want to know how can i display custom messages for invalid login in my custom login page.I followed the instructions you have provided in your blog to override the default login of alfresco with mine and it was helpful alot.So kindly help
blog_commenter
Active Member
Hi folks,
Thank you all for this post, it was very useful for me. After i have tried all the stuff that you have described I have choiced to adopt the solution proposed by chris for the semplicity and for the lack of time.

David, do you know other values that can be set in the  tag? because i would like to redirect the users to my custom home-page also when they complete a user task of a workflow and not only when they log in in share app.

Is the correct way to do this for you? in alternative I think to look into the form-runtime.js that is a Javascript that create the form for the task...

Anyway any advice is appreciated,
Thank again.

Francesco
blog_commenter
Active Member
Sorry for the stupid question... the behavior described above is already implemented!

Godd work guys.
blog_commenter
Active Member
[...] the first part of this tutorial I demonstrated how you could add a new page to Alfresco Share and have it protected by the standard [...]
blog_commenter
Active Member
Hi Dave,



Thanks for the post.



You said: 'There are 2 ways in which you can resolve this issue… the brute force approach would be to clear your database and delete your content store. Alternatively you can delete the “slingshot.site.configuration.xml” directly from the repository but to do this you will need to use the Repository client (i.e the original Alfresco client found at /alfresco rather than /share). Simply search for the file and then delete it… then your override file should take effect.'



I've searched all day through the repository via Alfresco Client, but couldn't locate the 'slingshot.site.configuration.xml' file.



Did a fresh installation and changed the theme, then I looked through the contentstore folder in alf_data and found the most-recently created file.



But, how can I locate the 'slingshot.site.configuration.xml' in a repository that has been running for months?



Regard.
ddraper
Intermediate II
My response was slightly misleading... you do need to search in the Explorer repository client (e.g. NOT Share)... but you need to search by exploring the navigation tree in Company Home. The config is intentionally hidden from search results, but this is one way of finding the files (they're not really intending to be found, but this is a work around).
blog_commenter
Active Member
Thanks a million, Dave!



I've found it.



Regards.
blog_commenter
Active Member
Hi,



How have the Share appearance our new page ?



Thank you in advance.
ddraper
Intermediate II
@Delizée... can you elaborate on your question please?
blog_commenter
Active Member
The new page does not include the header or footer of the Share interface.



I have so wanted to know how to give it the appearance Share
ddraper
Intermediate II
@Delizée Your new home page will need to map to a template that includes the 'share-header' and 'footer' regions (assuming you're on 4.2 Enterprise or 4.2.d Community - if not then there are different regions for the header).
blog_commenter
Active Member
You do not have a tutorial? Sorry but I only have a few days experience on alfresco and it is not easy ...
blog_commenter
Active Member
And yes, i m in 4.2
ddraper
Intermediate II
@Delizée The information you need is spread across multiple other blogs and examples in the source code. Unfortunately there is no specific blog post addressing your particular requirement in a step-by-step fashion at the moment.
blog_commenter
Active Member
Ok thanks