In GWT we need to use # in a URL to navigate from one page to another i.e for creating history for eg. www.abc.com/#questions/10245857 but due to which I am facing a problem in sharing the url. Google scrappers are reading the url only before # i.e. www.abc.com.
Now I want to remove # from my url and want to keep it straight as www.abc.com/question/10245857.
I am unable to do so. How can I do this?
When user navigates the app I use the hash urls and History object (as
to not reload the pages). However sometimes it's nice/needed to have a
pretty URL (e.g. for sharing, showing in public, etc..) so I would like to know how to
provide the pretty URL of the same page.
Note:
We have to do this to make our webpages url crawlable and to link the website with outside world.
There are 3 issues here, and each can be solved:
The URL should appear prettier to the user
Going directly to the pretty URL should work.
WebCrawlers should be able to get the content
These may all seem like the same issue, but they are quite distinct in this context.
Display Pretty URLs
Can be done with a small javascript file which uses HTML5 state methods. You can see a simple demo here, with source here. This makes all changes to "#" appear without the "#" (on modern browsers).
Relevent code from fiddle:
var stateObj = {locationHash: hash};
history.replaceState(stateObj, "Page Title", baseURL + hash.substring(1));
Repsond to Pretty URLs
This is relatively simple, as long as you have a listener in GWT to load based on the "#" at page load already. You can just throw up a simple re-direct servlet which reinserts the "#" mark where it belongs when requests come in.
For a servlet, listening for the pretty URL:
if(request.getPathInfo()!=null && request.getPathInfo().length()>1){
response.sendRedirect("#" + request.getPathInfo());
return;
}
Alternatively, you can serve up your GWT app directly from this servlet, and initialize it with parameters from the URL, but there's a bit of relative-path bookkeeping to be aware of.
WebCrawlers
This is the trickiest one. Basically you can't get around having static(ish) pages here. That's not too hard if there are a finite set of simple states that you're indexing. One simple scheme is to have a separate servlet which returns the raw content you normally fetch with GWT, in minimal formatted HTML. This servlet can have a different URL pattern like "/indexing/". These wouldn't be meant for humans, just for the webcrawlers. You can attach a simple javascript in the <head> to redirect users to the pretty url once the page loads.
Here's an example for the doGet method of such a servlet:
response.setContentType("text/html;charset=UTF-8");
response.setStatus(200);
pw = response.getWriter();
pw.println("<html>");
pw.println("<head><script>");
pw.println("window.location.href='http://www.example.com/#"
+ request.getPathInfo() + "';");
pw.println("</script></head>");
pw.println("<body>");
pw.println(getRawPageContent(request.getPathInfo()));
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
return;
You should then just have some links to these indexing pages hidden somewhere on your main app URL (or behind a link on your main app URL).
From current JSP I need to open new page with sending to it POST data. How I can make it?
In other words I need redirect from one page to another, but I cant use sendRedirect(because only GET) and requestDispatcher(because context of pages are different)
You have to create <form method="post">, fill the fields with respective data and submit it by JavaScript.
But on the other hand, what is your reason for that? There probably exists a cleaner solution.
Just make the behaviour that would happen if the initial POST data is received the default behaviour of the JSP when no post data is received.
e.g (in pseudo code - I don't know Java)
if (is_set(POST) ) {
if(POST == expectedInitialVals) {
defaultBahaviour();
} else {
handleOtherValues();
}
} else {
defaultBahaviour();
}
If you also want to persist the POST data in the page set the values on the relevant form fields in the page in your JSP.
First of all let me describe what I'm trying to do, which I'm guessing is pretty simple.
I have a website with users and want to restrict access to a view_profile.jsp page only to logged users. I have a filter mapped to:
<url-pattern>/auth/*</url-pattern>
which looks like this
try {
HttpSession session = ((HttpServletRequest)request).getSession();
UserBean user = (UserBean)session.getAttribute("currentUser");
if (user != null && user.isValid()){
System.out.println("Filter: context -> " + ((HttpServletRequest)request).getContextPath()); //returns ""
chain.doFilter(request, response);
}
else{
((HttpServletResponse)response).sendRedirect("/login.jsp"); //works fine
}
This filter is run when on the index.jsp page user will click on a link:
<a href="./auth/view_profile?profile=${sessionScope.currentUser.username}">
//yeah, he will 'view' himself - it's just an example
which is suppose to take the user to the servlet mapped to ViewProfileServlet mapped to:
<url-pattern>/auth/view_profile</url-pattern>
which looks like that:
try {
String username = (String) request.getParameter("profile");
// here is getting info from database and setting request attributes
// works fine
//response.sendRedirect("/view_profile.jsp");
System.out.println("ViewProfileServlet: In context -> " + getServletContext().getContextPath()); // returns ""
dis = getServletContext().getRequestDispatcher("/view_profile.jsp");
// i've tried request.getRequestDispatcher. no difference
System.out.println("ViewProfileServlet: forward to '/view_profile.jsp'");
dis.forward(request, response);
}
Which in turn should take the user to the /view_profile.jsp (in the root context, not in /auth) and work, which it doesn't. What happens is the ViewProfileServlet runs and the view_profile.jsp shows, although it seems that the context is still /auth because all the links on view_profile.jsp point to i.e localhost:8080/auth/some-page.jsp. Also, css files are not being loaded, they're not even requested (at least according to firebug), and page source shows 404 Glassfish Error where css's suppose to be.
I would greatly appreciate any help, it's the first time i'm even doing something in jsp and i'm completely lost here.
A forward happens entirely at server-side. The browser doesn't know about it. When it sends a request to /auth/view_profile, and receives HTML from this response, he doesn't care if the HTML has been generated by a servlet, a JSP, both, or anything else. It reads the HTML and considers it comes from the path /auth/view_profile. All the relative path in the HTML are thus relative to /auth/view_profile.
It's far easier to use absolute paths to reference images, JS and CSS paths (and even other actions, most of the time). Just make sure to use the <c:url> tag to generate the URL, so that the context path of the web-app is prepended:
<script src="<c:url value='/js/myScript.js'/>" type="text/javascript"/>
^-- the slash here makes the path absolute.
I'm noticing some odd behavior with redirect when I set my app.context a certain way. I found a bug in the Grails JIRA which describes my problem perfectly, but it was marked as UTR: http://jira.grails.org/browse/GRAILS-7546
Here is my description of the problem:
I'm currently using Grails 2.0M2. I have the following properties defined in my application.properties file:
app.context=/
app.name=foobar
When I call redirect in a controller, redirect is adding the app name onto the uri I provide, which then causes a 404. Here is how I'm doing this:
String partialUrl = createLink(mapping: 'helloworld') // returns `/hello/world`
redirect(uri: partialUrl) // INCORRECTLY redirects to
// `http://mysite.com/foobar/hello/world`
// instead of `http://mysite.com/hello/world`
Assume that I have a URL mapping named helloworld defined in my UrlMappings.groovy file with a path of /hello/world.
So, long story short, if I set the app.context to /, I would NOT expect the app.name to show up in my final redirect URL.
Is this a bug or expected behavior? Any idea on the easiest way I could build up the redirect URL without doing too many manual steps?
I hate to say it, but I cannot reproduce it either. I created a test project with one controller (named Hello), using your code to create an action that does nothing but redirect:
HelloController.groovy
package test1
class HelloController {
def index() {
def model = [:]
model.content = 'content...'
model
}
def redir() {
String partialUrl = createLink(mapping: 'helloworld') // returns `/hello/world`
redirect(uri: partialUrl) // INCORRECTLY redirects to
// `http://mysite.com/foobar/hello/world`
// instead of `http://mysite.com/hello/world`
}
}
I created an index page, index.gsp in the views/hello
index.gsp
<h1>index.gsp</h1>
<html>
<body>
<p>This data is coming from the model:</p>
<p>content: ${content}</p>
</body>
</html>
Setup helloworld in the UrlMappings to map to the index action of the hello controller:
UrlMappings.groovy
class UrlMappings {
static mappings = {
"/helloworld"(controller: "hello", action: "index")
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
}
And changed the application.properties to have the app.context=/
application.properties
#Grails Metadata file
#Sun Nov 06 14:51:56 EST 2011
app.grails.version=2.0.0.RC1
app.context=/
app.name=test1
app.servlet.version=2.5
app.version=0.1
When I ran the app, I could go to localhost:8080/hello and it would show my simple GSP. I tried localhost:8080/helloworld and also got it as expected per the mapping. Then I tried localhost:8080/hello/redir and I was properly redirected to localhost:8080/helloworld.
However, if you're still facing this issue, I have a few suggestions
1) Try using the new link generator available in 2.0 instead of createLink. It may not do anything different, but worth a try: grailsLinkGenerator.link(mapping: 'helloworld')
2) If it's only on redirects from within controllers, you could just add the http://mysite.com portion yourself to the partialUrl.
3) Last resort, write a Filter attached to afterView that does a regex search and replace on the contents for mysite.com/foobar. Not sure this will catch redirects though, but if anything would, I'd assume this would be it since filters can be applied at broad level.
def yourAction = {
redirect(uri:"helloworld")
}
That doesnt work for you?
It's not a direct anwser to your question but my practice is : I never modify app.context in the grails properties since tomcat override it on production and I don't care which context it uses on my dev.
What's the best way to externalize large quantities of HTML in a GWT app? We have a rather complicated GWT app of about 30 "pages"; each page has a sort of guide at the bottom that is several paragraphs of HTML markup. I'd like to externalize the HTML so that it can remain as "unescaped" as possible.
I know and understand how to use property files in GWT; that's certainly better than embedding the content in Java classes, but still kind of ugly for HTML (you need to backslashify everything, as well as escape quotes, etc.)
Normally this is the kind of thing you would put in a JSP, but I don't see any equivalent to that in GWT. I'm considering just writing a widget that will simply fetch the content from html files on the server and then add the text to an HTML widget. But it seems there ought to be a simpler way.
I've used ClientBundle in a similar setting. I've created a package my.resources and put my HTML document and the following class there:
package my.resources;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;
public interface MyHtmlResources extends ClientBundle {
public static final MyHtmlResources INSTANCE = GWT.create(MyHtmlResources.class);
#Source("intro.html")
public TextResource getIntroHtml();
}
Then I get the content of that file by calling the following from my GWT client code:
HTML htmlPanel = new HTML();
String html = MyHtmlResources.INSTANCE.getIntroHtml().getText();
htmlPanel.setHTML(html);
See http://code.google.com/webtoolkit/doc/latest/DevGuideClientBundle.html for further information.
You can use some templating mechanism. Try FreeMarker or Velocity templates. You'll be having your HTML in files that will be retrieved by templating libraries. These files can be named with proper extensions, e.g. .html, .css, .js obsearvable on their own.
I'd say you load the external html through a Frame.
Frame frame = new Frame();
frame.setUrl(GWT.getModuleBase() + getCurrentPageHelp());
add(frame);
You can arrange some convention or lookup for the getCurrentPageHelp() to return the appropriate path (eg: /manuals/myPage/help.html)
Here's an example of frame in action.
In GWT 2.0, you can do this using the UiBinder.
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
<div>
Hello, <span ui:field='nameSpan’/>, this is just good ‘ol HTML.
</div>
</ui:UiBinder>
These files are kept separate from your Java code and can be edited as HTML. They are also provide integration with GWT widgets, so that you can easily access elements within the HTML from your GWT code.
GWT 2.0, when released, should have a ClientBundle, which probably tackles this need.
You could try implementing a Generator to load external HTML from a file at compile time and build a class that emits it. There doesn't seem to be too much help online for creating generators but here's a post to the GWT group that might get you started: GWT group on groups.google.com.
I was doing similar research and, so far, I see that the best way to approach this problem is via the DeclarativeUI or UriBind. Unfortunately it still in incubator, so we need to work around the problem.
I solve it in couple of different ways:
Active overlay, i.e.: you create your standard HTML/CSS and inject the GET code via <script> tag. Everywhere you need to access an element from GWT code you write something like this:
RootPanel.get("element-name").setVisible(false);
You write your code 100% GWT and then, if a big HTML chunk is needed, you bring it to the client either via IFRAME or via AJAX and then inject it via HTML panel like this:
String html = "<div id='one' "
+ "style='border:3px dotted blue;'>"
+ "</div><div id='two' "
+ "style='border:3px dotted green;'"
+ "></div>";
HTMLPanel panel = new HTMLPanel(html);
panel.setSize("200px", "120px");
panel.addStyleName("demo-panel");
panel.add(new Button("Do Nothing"), "one");
panel.add(new TextBox(), "two");
RootPanel.get("demo").add(panel);
Why not to use good-old IFRAME? Just create an iFrame where you wish to put a hint and change its location when GWT 'page' changes.
Advantages:
Hits are stored in separate maintainable HTML files of any structure
AJAX-style loading with no coding at all on server side
If needed, application could still interact with loaded info
Disadvantages:
Each hint file should have link to shared CSS for common look-and-feel
Hard to internationalize
To make this approach a bit better, you might handle loading errors and redirect to default language/topic on 404 errors. So, search priority will be like that:
Current topic for current language
Current topic for default language
Default topic for current language
Default error page
I think it's quite easy to create such GWT component to incorporate iFrame interactions
The GWT Portlets framework (http://code.google.com/p/gwtportlets/) includes a WebAppContentPortlet. This serves up any content from your web app (static HTML, JSPs etc.). You can put it on a page with additional functionality in other Portlets and everything is fetched with a single async call when the page loads.
Have a look at the source for WebAppContentPortlet and WebAppContentDataProvider to see how it is done or try using the framework itself. Here are the relevant bits of source:
WebAppContentPortlet (client side)
((HasHTML)getWidget()).setHTML(html == null ? "<i>Web App Content</i>" : html);
WebAppContentDataProvider (server side):
HttpServletRequest servletRequest = req.getServletRequest();
String path = f.path.startsWith("/") ? f.path : "/" + f.path;
RequestDispatcher rd = servletRequest.getRequestDispatcher(path);
BufferedResponse res = new BufferedResponse(req.getServletResponse());
try {
rd.include(servletRequest, res);
res.getWriter().flush();
f.html = new String(res.toByteArray(), res.getCharacterEncoding());
} catch (Exception e) {
log.error("Error including '" + path + "': " + e, e);
f.html = "Error including '" + path +
"'<br>(see server log for details)";
}
You can use servlets with jsps for the html parts of the page and still include the javascript needed to run the gwt app on the page.
I'm not sure I understand your question, but I'm going to assume you've factored out this common summary into it's own widget. If so, the problem is that you don't like the ugly way of embedding HTML into the Java code.
GWT 2.0 has UiBinder, which allows you to define the GUI in raw HTMLish template, and you can inject values into the template from the Java world. Read through the dev guide and it gives a pretty good outline.
Take a look at
http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideClientBundle.html
You can try GWT App with html templates generated and binded on run-time, no compiling-time.
Not knowing GWT, but can't you define and anchor div tag in your app html then perform a get against the HTML files that you need, and append to the div? How different would this be from a micro-template?
UPDATE:
I just found this nice jQuery plugin in an answer to another StackOverflow question.