as I asked time ago in this question, I solved my problem using this method:
In loging.xhtm, for instance:
<f:view locale="#{languageDetails.locale}" >
<head>
.....
<f:loadBundle basename="messages.Messages" var="msg1"/>
.....
</h:form>
</body>
</f:view>
2.In java source code I also made some changes:
public class LanguageDetails {
private static String locale = Locale.getDefault().getDisplayLanguage();
public void setLocale(String locale1) {
this.locale = locale1;
}
public synchronized String getLocale() {
return locale;
}
public synchronized String changeLanguage() {
return "changed";
}
}
But now I'm trying to have the same option, not just in Login page, but in other pages.
Adding the same code in other pages, doesn't work, because function setLocale is not called. Any help?
Thanks in advance
I realized, it's really important to put
<f:view locale="#{languageDetails.locale}" >
....
</f:view>
Or in every single file, or just in top file. Later, put <h:selectOneMenu> where necessary, but having always in mind that you can not have all <h:form> , <a4j:form>... etc. you want, it makes things more complicated. I put this form tags just on top files, and now everything is ok.
Hope this could help somebody.
Related
I'm trying to update a whole page in adf when you click on a link to go to the same page with new page parameters. If I open the link in a new tab, it works fine, but opening it in the same tab doesn't update.
I have a page that just displays the parameter value from the url, a link to the same page with a different parameter value, and an output text that displays the datetime. My taskflow starts by calling RetrieveDateTime() and then goes to refrestTest.jsff. The taskflow is a region on refresh.jsf page.
public class RefreshDC {
private String dateTime;
public RefreshDC() {
super();
}
public void RetrieveDateTime() {
System.out.println("DC RETRIEVEDATETIME");
RefreshFacade rf = new RefreshFacade();
this.dateTime = rf.getDate().getDatetime();
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public String getDateTime() {
return dateTime;
}
}
The page fragment:
//refreshTest.jsff
<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:panelGroupLayout id="pgl1" layout="vertical">
<af:outputText value="#{param.id}" id="ot1"/>
<af:goLink text="RP PDTLS" id="gl1" destination="/faces/refresh.jsf?
id=1234567890"/>
<af:outputText value="DateTime: #{bindings.dateTime.inputValue}"
shortDesc="#{bindings.dateTime.hints.tooltip}" id="ot2"
partialTriggers="gl1"/>
</af:panelGroupLayout>
</ui:composition>
The page:
//refresh.jsf
<f:view xmlns:f="http://java.sun.com/jsf/core"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:document title="refresh.jsf" id="d1">
<af:form id="f1">
<af:region value="#{bindings.refresh1.regionModel}" id="r1"/>
</af:form>
</af:document>
</f:view>
As i said, if you open the goLink in a new tab, it will update the dateTime, however if you open it in the same tab, dateTime remains the same. (The param.id does update in both cases)
You can refresh the whole page programatically by replacing your golink by an adf button with an ActionListener calling the following java bean function :
public static void refreshPage() {
FacesContext fc = FacesContext.getCurrentInstance();
String refreshpage = fc.getViewRoot().getViewId();
ViewHandler ViewH = fc.getApplication().getViewHandler();
UIViewRoot UIV = ViewH.createView(fc, refreshpage);
UIV.setViewId(refreshpage);
fc.setViewRoot(UIV);
}
I managed to solve this using the taskflow. Basically, I made the button go to a new page with a region. This region has a taskflow that reads the url parameters and if it matches my conditions, links back to the original page with new parameters (toDocumentsPage). Otherwise, goes to a different page (searchResults).Taskflow to refresh the page
I want to implement an i18n-support for a wicket 7 application.
Requirements:
Translations must be easily editable by the admin-user
Translations must take place without redeployment
My actual apporach is to hold the translations inside a DB. All translations will be cached. If a translation is changed by a Frontend-task the cache and the db will be updated.
So far so easy.
Actually I'm stuck in replacing the translations inside a page.
A working solution would be loading every translation during implementation. These translations would be set inside many of wicket-elements.
I don't like this approach, because it'll mess up the code (html + java) heavily.
I'll try to implement a replacement-mechanism in my actual approach. After the page is rendered, the mechanism is run through the whole page and is doing these jobs:
search for all placeholders
load the translation for the placeholder-keys(cache)
replace the placeholders with the translations
This should work for body and header (site's title)
Here is an example of a wicket-template
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${landingpage.site.title}</title>
</head>
<body>
<header wicket:id="headerPanel">header</header>
${welcome.message}
<footer wicket:id="footerPanel">footer</footer>
</body>
</html>
In this case ${landingpage.site.title} and ${welcome.message} should be recognized and replaced. As you can see it is directly definied inside the template, not in the java-code. And this is what I want to achieve.
I hope I made the requirements clear enough. If not, don't mind to comment. I'll update the question to make it more clear.
My approach is to implement a BasePage (extends Page) and overwrite the onAfterRender-Method
#Override
protected void onAfterRender() {
super.onAfterRender();
Response originalResponse = RequestCycle.get().getResponse();
String updatedResponse = replaceWithTranslations(originalResponse);
originalResponse.reset();
originalResponse.write(updatedResponse);
}
The method replaceWithTranslations is not yet implemented and returns a simple String actually. This method should convert the outputstream of the originalRepsonse to a String, searches for placeholders and replace them with the values of the db.
This approach seems to have 2 difficulties:
I'm not getting the response as String
I'm getting a WicketRuntimeException (Page.checkRendering in Page.java:666)
Any advice would be great!
OK, the problems seems to be a very simple one.
The trick or the luck is, here we have a BufferedWebResponse. A simple cast will do the trick:
#Override
protected void onAfterRender() {
super.onAfterRender();
BufferedWebResponse originalResponse = (BufferedWebResponse) RequestCycle.get().getResponse();
String translatedResponse = replaceWithTranslations(originalResponse);
originalResponse.reset();
originalResponse.write(translatedResponse);
}
private String replaceWithTranslations(BufferedWebResponse originalResponse) {
String untranslatedText = originalResponse.getText().toString();
String translatedText = doTheTranslation(untranslatedText);
return translatedText;
}
Inspired by #RobAu I gave the wicket's approach of i18n a chance. Here is with what I came up with:
The template:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><wicket:message key="landingpage.site.title">Site-Title</wicket:message></title>
</head>
<body>
<header wicket:id="headerPanel">header</header>
<wicket:message key="welcome.message">Welcome</wicket:message>
<footer wicket:id="footerPanel">footer</footer>
</body>
</html>
wicket:message for attributes:
<input type="text" placeholder="username" wicket:message="placeholder:login.username"/>
The IStringResourceLoader:
#org.springframework.stereotype.Component
public class I18NResourceLoader implements IStringResourceLoader {
#Autowired
private I18NCache i18nCache;
#Override
public String loadStringResource(final Class<?> clazz, final String key, final Locale locale, final String style, final String variation) {
return loadTranslation(key, locale);
}
#Override
public String loadStringResource(final Component component, final String key, final Locale locale, final String style, final String variation) {
return loadTranslation(key, locale);
}
private String loadTranslation(final String key, final Locale locale) {
final Optional<Translation> optional = i18nCache.get(key, locale);
if (!optional.isPresent()) {
return key;
}
return optional.get().getText();
}
}
Translation and I18NCache are self-implemented classes.
And finally the registration:
public abstract class BasePage extends WebPage {
#SpringBean
private I18NResourceLoader i18NResourceLoader;
public BasePage(){
addI18NResourceLoader();
...
}
private void addI18NResourceLoader() {
final List<IStringResourceLoader> resourceLoaders = Application.get().getResourceSettings().getStringResourceLoaders();
final boolean existsResourceLoader = resourceLoaders.stream()
.filter(p -> p instanceof I18NResourceLoader)
.collect(Collectors.counting()) > 0L;
if (!existsResourceLoader) {
resourceLoaders.add(i18NResourceLoader);
}
}
...
}
Pro's:
Wicket's approach
No mess with RegEx-Replacement-Handling
SPR
Con's
Template feels a little more messy
Actually, I have no informations about the performance of this approach.
I decided to keep the logic of adding the ResourceLoader in BasePage by 2 reasons.
BasePage is responsible for everything concering the page-representation (weak reason :-) )
I'm using DI. If I would add the logic in the WebApplication, I would have to manually inject the I18NResourceLoader or its dependencies.
I think you can extend IComponentResolver to replace the placeholders like WicketMessageResolver.
After migrating wicket to 1.5 I encounter this issue.
In Wicket 1.5 I (programmer before me) was adding JS and CSS reference in constructor and then component, simmilar to this:
public abstract class PageTemplate extends WebPage implements IHeaderContributor {
public BarePageTemplate() {
this(null);
}
public BarePageTemplate(PageParameters params) {
super(params);
add(JavascriptPackageResource.getHeaderContribution(ResourceMarker.class, "js/jquery-1.4.2.min.js"));
add(JavascriptPackageResource.getHeaderContribution(ResourceMarker.class, "js/jquery-ui-1.8.4.custom.min.js"));
[...]
jGrowlMarker = new Label("jGrowlMarker"); // placeholder for jgrowl messages
jGrowlMarker.setOutputMarkupId(true);
jGrowlMarker.add(new JGrowlBehavior());
add(jGrowlMarker);
}
}
In wicket 1.5 this is no longer possible. According to migration guide I refactored this code into this:
public abstract class PageTemplate extends WebPage implements IHeaderContributor {
public BarePageTemplate() {
this(null);
}
public BarePageTemplate(PageParameters params) {
super(params);
jGrowlMarker = new Label("jGrowlMarker"); // placeholder for jgrowl messages
jGrowlMarker.setOutputMarkupId(true);
jGrowlMarker.add(new JGrowlBehavior());
add(jGrowlMarker);
}
#Override
public void renderHead(IHeaderResponse response) {
response.renderJavaScriptReference(new CommonResourceRef("js/jquery-1.4.2.min.js"));
response.renderJavaScriptReference(new CommonResourceRef("js/jquery-ui-1.8.4.custom.min.js"));
[...]
}
}
This piece of code works, what I mean by that is that it includes those js. What causing me an issue is fact that right now my component (in this case jGrowlMarker) is rendering in page before page includes those js:
// jGrowl component
<script type="text/javascript" src="./wicket/resource/pl.softq.commons.ui.resource.ResourceMarker/js/jquery-1.4.2.min-ver-65B352E1BA79F0E2A3B1E014BC2571AF.js"></script>
<script type="text/javascript" src="./wicket/resource/pl.softq.commons.ui.resource.ResourceMarker/js/jquery-ui-1.8.4.custom.min-ver-88A9784D8E08D25998F239E2D65F03D7.js"></script>
Because of that it doesn't work properly (I believe thats an issue). It tries to create jGrowl component but jGrowl.js is added after this component.
[...] symbolizes rest of my js and css refenreces (including jGrowl ones). I've tried to add super.renderHead(response); to renderHead but it also doesnt work (super.renderHead refers to empty one in Component.class).
So my question is: how to add component after renderHead initializes or how to add it inside renderHead.
I'm not an expert in wicket so if you need more piece of code, let me know.
You can move the renderHead() method to JGrowlBehavior. This way it will contribute the dependencies first and then jgrowl.js itself.
If the dependencies are contributed by something else in the page too Wicket will detect this and contribute them just once.
In Wicket 6.x there are further improvements in this area. You can read http://wicketinaction.com/2012/07/wicket-6-resource-management/
First sorry for my english...
I was searching for all internet but I can't find the answer of my question. I tried everything, looked in documentation, tutorials, videos, etc...
I put two buttons in the top of my page for the user can change the language, but I can't catch the value on my controller, I did everything but never can handle. I'm new on play :( please help...!!
I have this on my view:
<`form method="GET" action="#{Application.language("value")}"/`>
<`input> name="language" type="submit" value="en" title="#Messages("button.en")" </`>
<`input> name="language" type="submit" value="es" title="#Messages("button.es")" </`>
<`/form`>
And this on my controller:
public static void language(String idiom) {
String key = null;
key = idiom;
if(key.isEmpty()){
} else {
Lang.apply(idiom);
}
}
But when I try to catch the value on my controller always I received this message:
[RuntimeException: Unrecognized language: value]
Your HTML looks a little suspect, can you clean it up and repost along with your controller and route?
In the meanwhile, this is roughly what I'd expect to see to make sure your parameters get passed in properly:
Routes:
GET /language #controllers.LanguageController.index(language: String)
Controller:
LanguageController {
...
public Result index(String language) {
if(language != null && !language.isEmpty()){
Lang.apply(idiom);
}
... return
}
}
To make the setting stick in Play 2, see this post
playframework 2.2 java: how to set language (i18n) from subdomain
I did it a little modification with your comment below and this is how I have now.
Route:
POST / #controllers.LanguageController.changeLanguage(language: String)
View:
<form method="POST" action="changeLanguage("value")"/>
<input name="language" type="submit" value="en" title="English" </>
<input name="language" type="submit" value="es" title="Spanish" </>
</form>
Controller:
public class LanguageController extends Controller{
public Result changeLanguage(String language)
{
if(language != null && !language.isEmpty())
{
Lang.apply("en");
}
else
{
String idiom = language;
Lang.apply(idiom);
}
return ok(index.render(""));
}
Now I have this message error:
For request 'POST /changeLanguage(value)'
And the page error shows the route of the LanguageController this:
POST/#controllers.LanguageController#.changeLanguage(language:String)
You have messages.{lang} ( like messages.es or messages.en) in conf folder right?
And in application.conf valid langs should exist like;
application.langs="en,es"
If you have these so in any class which extends Controller you can run this method;
changeLang("es");
But in your case it seems that value of the idiom in your function is "value"
So if it's fine for you just replace the form header as;
<form method="GET" action="/language"/>
(assuming that /language will route to your method)
and replace the names of the html inputs as "idiom"
so you will be passing the right value of the input.
In play 2.8, Http.Context was deprecated which lead to changes in the interaction with the response object.
To change the language you need to do the following:
Inject an instance of MessagesApi into your controller
Create an instance of Lang object with the language you intend to use
Use method .withLang(Locale locale, MessagesApi messagesApi) on your result object
Code to illustrate:
private final MessagesApi messagesApi;
#Inject
public LoginController(MessagesApi messagesApi) {
this.messagesApi = messagesApi;
}
// ... now in the method invoked by the router
Lang lang = Lang.apply("en"); //english language
return ok().withLang(lang.toLocale(), messagesApi);
This changes the language throughout the rest of the session, since play will store the language in the cookie PLAY_SESSION. If you want to change only for one particular request, you must change the request object instead of the result object.
Reference here
One DropDownChoice list on my webapp takes very long time to create, because of getting options by some operations with LDAP connection and SQL connection. And because of that the whole page is loading much more than a couple of seconds - I'd say too much.
So what I want to achieve, is to use (best for me) the built-in Ajax functionality of Wicket to lazy load this dropdown, but I have some problems.
I know how to make regular DropDownChoice list, this simple example working great for me - link
I also know how to make lazy-loaded paragraph, from wicket-examples - link (Source Code -> LazyLoadingPage.html/LazyLoadingPage.java)
But putting it together throwing me exceptions and resulting Wicket's Internal error.
Here is how I try to do it:
in HTML:
<select wicket:id="lazy"></select>
in Java:
private String selected = "abc";
(...)
add(new AjaxLazyLoadPanel("lazy") {
#Override
public Component getLazyLoadComponent(String id) {
//simulating long time for simple list
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new DropDownChoice<String>(
id, new PropertyModel<String>(this,"selected"),
Arrays.asList("abc","def"));
}
});
}
And I'm getting Internal Error from Wicket, with that in logs:
ERROR Unexpected error occurred
Component [content] (path = [0:lazy:content]) must be applied to a tag of type [select], not: '<div wicket:id="content">' (line 0, column 0)
MarkupStream: [markup = jar:file:/C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%207.0/webapps/devservices/WEB-INF/lib/wicket-extensions-1.5.7.jar!/org/apache/wicket/extensions/ajax/markup/html/AjaxLazyLoadPanel.html
, index = 0, current = ''
and stacktrace.
I would really appreciate some help, what I'm doing wrong, or maybe some better code examples.
Thanks to bert, I'm putting here full solution, in case someone will use it in the future.
We need to create our own panel, because AjaxLazyLoadPanel can only change one panel to another.
Example of MyPanel.html:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:panel>
<select wicket:id="project"></select>
</wicket:panel>
</body>
</html>
and MyPanel.java :
public class MyPanel extends Panel {
private String selected = <what you want>;
private List<String> projectList <what you want>;
public MyPanel(String id) {
super(id);
add(new DropDownChoice<String>(
"project", new PropertyModel<String>(this, "selected"), projectsList));
}
}
On your main page html simply add this:
<span wicket:id="lazy2"></span>
and in main page java file:
add(new AjaxLazyLoadPanel("lazy") {
#Override
public Component getLazyLoadComponent(String id) {
return new MyPanel(id);
}
});
Hope it will help someone else too :-)