In Stuts2 I am using Tiles plugin to create a layout for the website (menu, footer, header etc.) that is consistent on every page.
Now each tile is just a static HTML content.
Is it possible to make a Tile more dynamic by eg. calling a Footer action class every time the footer is to be rendered? For example: to fetch footer content from database.
If I was to do that inside every page's action class in my application this would make for a very unusable code...
So maybe it is possible from Tile perspective?
There is only one way to do what you ask with a tiles version less than 2.2.2 and that is with a "preparer".
This however is not an integration with struts2 but would mean the preparer it self will access the service layer to get the required content for the view and all that content would need to be set though tiles attributes.
With tiles versions 2.2.2 and higher:
You can use OGNL expressions within tiles attributes, this can allow access to some struts2 interaction as well as static method access. With static method access you can call a method to return a string how ever you want. Creating such a string would be on par with writing a scriptlet.
To upgrade you need to either manually override some jars to get tiles 2.2.2, or to get version three you will need to implement your own result type: How to integrate Struts 2 with Tiles 3.
I don't actually recommend either of the above methods at this time, tiles 3 is recommended but not as an excuse to do something as bad as writing a scriptlet. It would probably be better to use the s:action tag in a tile, as mentioned by David or use an Ajax method as mentioned by Jaiwo99. The reason being that both these methods keep with struts2 while the ones I presented would be unusual and be harder to maintain. Personally I would lean towards the ajax methods.
Struts2 along with the struts2-json-plugin makes creating json services very simple. Tiles is a nice system for reducing boiler plate. If ajax is used heavily the two really can compliment each other. You can make a lot of reusable ajax components, just be sure to not hard code the urls of actions. Always use the s:url tag and assign that to JS variables.
Try following code:
$('#footer').load('your/action/with/namespace');
i'm assuming your footer is with id footer, everytime you open a page, your footer action class will be called and the data can be fetched dynamically.
Related
I have a project which gives the user interface to create the Dynamic forms on the fly.
User can select different fields like textbox, textarea, date etc and create a model for the same.
Once the user chooses the component and creates a form, then we need to show that form at a specifies place. The form components are rendered through common jsp page which accepts pojo object and then distributes that object to our own custom created tags for input,checkbox,radio,date etc.
Issue is it takes very 10-15 seconds to render the form.
Is there a way i can create templates or say html code of created forms and store them in DB and render through them. (Provided i am able to still bind data using Spring MVC, show dropdown values, selected or saved data in the fields.)
You may want to take a look at Metawidget. It renders different forms inside a common JSP as you describe, and does not have the 10-15 second issue you are seeing.
Metawidget is Open Source, so you can examine how it works, or even use it 'as is' (it is designed to be embedded inside projects such as yours). There's a good example tutorial here: http://metawidget.org/doc/reference/en/html/ch01s03.html#section-introduction-part2-web
Better way is to create you own custom tags and remove repeated code.
This will decrease the compilation time and further decreases the loading time of the page.
I'm interested in the Tapestry framework put have some problems with it due to several reasons:
The output I have to generate has to be XML. According to http://tapestry.apache.org/content-type-and-markup.html this is no big deal.
But when it comes down to use actionlink, components or all the other Tapestry goodies, the resulting code should not be anchor or div but some custom xml elements/attributes.
Is it possible to archieve this without alot of pain?
Workarounds or insides to the background mechanismn of Tapestry are welcome.
while actionlink will always render as an anchor (a) tag, the Any component can render as any arbitrary xml element, and it and many other tapestry components will render arbitrary (informal) parameters depending on their definition.
for example, (assuming you have a java method called 'getTheTime' in your class, mine returns System.currentTimeMillis())
<xyz t:type="actionlink" t:id="someaction">
a element</xyz>
<xyz t:type="any"
attribute1="${theTime}"
attribute2="prop:theTime"
attribute3="theTime">
xyz element</xyz>
will render as:
a element
<xyz attribute1="1338418847753" attribute2="1338418847753"
attribute3="theTime">xyz element</xyz>
In order to get a combination of the two, you will need to roll your own component. This is pretty simple once you understand tapestry a little better.
Have a look at the source of ActionLink.java (and its super classes) and you should be able to figure it out.
I have a web-app in Java, Spring, Struts 2 and Hibernate, that servers multiple clients. Each client with multiple users. To create a personal feel for each client, i would like to customize the header for each client.
I'm using sitemesh as decorator, and am looking for tips or examples or someone who can point me in the right direction as to how to acomplish this in the best practice.
What would you think? Should i just code it direct in the header.jsp? Extracting the info about the logged in user and from that create a custom header by code? Or is there a more clever solution out there?
Thanks!
Update:
To further clearify what i want:
Different properties-files for each client is not an option. We are looking at potentionally hundreds of clients. It needs to be database-driven. But thats the easy part. There is no problem storing the information in db and extracting it when needed.
What im trying to figure out is if there is some sort of standard way of doing this. Some sort of filter or Action that is run before the sitemesh decorator that will provide the decorator with the correct info?
Struts2 provides application scope, for variables which are global to the application.
Load all the customer specific strings into #application scope (I would use spring to do this when the application starts up). From there referencing the strings would be pretty obvious: #application.greeting I don't like the idea of using an interceptor because there is nothing to intercept. I would say for what you are doing application scope is the perfect place. If it is a single client system I can see no reason why anything would be stored in application scope.
Aside: Tiles uses a different template paradigm than site mesh, and they have slightly different purposes. As such the two can be complimentary. Tiles relying on XML definitions can have it's definitions stored in a DB and is definitely less computationally intensive, however where there is interplay between different UI components... or disparate elements appearing on the page you need to use sitemesh. So for basic template needs tiles does everything and is quite easy to understand but say you wanted to make add a certain widget in the middle of the page which relies on JS which needs to be added to the header it would be tricky to do this in Tiles (although the obvious solution is to just roll the JS functionality into one JS file for all possible uses in a particular part of the site).
Asside 2: By using a view technology such as velocity or freemarker in conjunction with tiles it is conceivable to move the entire view layer into a database. I just thought I would mention that as for some maintenance issues that could be extremely beneficial.
Sitemesh makes it's decisions about what decoration to use based upon the requested URL string, so unless you have a reference to the client in every url - either as part of the main url string or as a known parameter, then Sitemesh out of the box is not going to help.
This leaves a few possibilities to achieve what you want;
1) Write a filter that runs before Sitemesh that adds, for example, "&clientId="xx" to every incoming request.
2) Dive into the source code for Sitemesh & look for where Sitemesh finally makes it's decision about which decorators to use and override it. I've never tried this so I don't know how practical this might be.
3) Make the style sheet definition in your jsp pages an OGNL expression and provide that information in a base action class that all your actions extend. In this way you end up with (potentially) a different CSS file for each client and you provide your customisation via CSS.
Hope that this helps.
Working on a large Web app, I have houndresds of JSPs.
Each JSP includes (ONLY) a set of internal tags, for instance:
<AAA:INPUT value="bbb" state="<%=getPageState()"/>
This tag is rendered into an HTML input field, with a readonly/enabled state, based on the return value from getPageState().
This basically allows me to set the complete page as enabled/disabled from a single entry point.
I don't like this (mainly because it drives me away from writing the HTML I want and I need to maintain attributes for each HTML attribute I want), I know I can something similar on client side with JavaScript.
Are there other approachs to control the state of a complete JSP form in a single point on the web-server side?
The way I would go about this would be to convert the getPageState() method into a tag, and then use this tag within your custom tags. That way, you don't need to explicitly pass in the page-state on every invocation of your custom tag.
Of course, this means that you would have to modify all your custom tags to use this new tag, but I think that's better than having your code littered with explicit calls to get the page state. Not to mention, an opening for inconsistencies if a developer forgot to check the page state.
Also, now the decision as to how the element needs to be rendered rests in the custom tag itself (where it belongs).
The only problem I see is that now you have to make multiple (redundant) calls per element to get the page state, which is not that efficient. To get around this problem, you can have your custom tag (that gets the page state) set a page attribute, and have your custom tags inspect this page attribute to decide if the form element should be disabled or not (another way would be to create a variable with the scope AT_END).
It's common to have many pages in a website that request the same model attributes, for example, a header that renders the current users name, or a column that needs a few server based pieces of information.
...
<body>
<mytaglib:header/>
...
<jsp:include page="footer.jsp"/>
...
</body>
The simplest solution is that every controller method you write that returns views that use the header, or footer also add all of attributes needed by components contained within it, but as the site grows it can become difficult to handle, particularly when you start dealing with pages that don't all have exactly the same components.
Is there a way to encapsulate the logic that adds to the model based on sub-pages or tags?
Well, you could do that in a few ways. The following pop in mind:
Put your logic in a Filter that places the information in request scope;
Spring has something similar to a Filter called an Interceptor. You can place your logic here and again save it in request scope.
Have the logic behind a custom tag that is inserted into your pages. There is a disadvantage to this because you must insert the tag in each JSP. If you are using a decorator filter like SiteMesh then you could place this once in your decorator JSPs and be done with it.
Have the logic in a parent controller that all your controllers will extend.
Do you use a framework in particular? If you only use servlets I would suggest you to create a base servlet class, if using spring I will suggest you to create a Base SPring MVC Controller. ANd you can set these attributes from the base class or use filters :)