I have this website made with Angular that I'm trying to serve. When doing it just with Springboot and Maven I have no problem. The webpage is encoded correctly with UTF-8. Now I'm trying to serve the page with Google Appengine and Springboot and it gets served without UTF-8.
In my pom.xml I have this line
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
And in the app engine-web.xml
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
<property name="file.encoding" value="UTF-8" />
<property name="DEFAULT_ENCODING" value="UTF-8" />
</system-properties>
I'm still learning all of this but it feels like everything should be served with UTF-8.
Are you sure that
You don't have any ISO-8859-1 characters on the page, and
The static HTML includes <meta charset="UTF-8"> (HTML5) or <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> (otherwise)
Related
I'm new to spring framework and I was able to run my index.html from my localhost but all resources won't show. Below is my folder structure
- src/main
- webapp
- resources
- css (All css files)
- fonts (All font files)
- images (All image files)
- js (All js files)
- static
- index.html (my index.html)
- WEB-INF
My index.html page:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta charset="utf-8" />
<title>My First Application</title>
<meta name="description" content="overview & stats" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<!-- bootstrap & fontawesome -->
<link rel="stylesheet" href="/resources/css/bootstrap.min.css" />
<link rel="stylesheet" href="/resources/font-awesome/4.5.0/css/font-awesome.min.css" />
.........
In the "href" I tried changing the directory path multiple times, the page is loading but just a bunch of texts (No css, image, etc)
Do I also need to update my servlet-context.xml or web.xml?
EDIT:
I checked servlet-context.xml and the mapping already exists for resoucres:
<mvc:resources mapping="/static/**" location="/static/" />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
I even added:
<resources mapping="/resources/css" location="/resources/css" />
<resources mapping="/resources/fonts" location="/resources/fonts" />
<resources mapping="/resources/images" location="/resources/images" />
but still won't work.
EDIT 2:
When I go to chrome - inspect - console. This is the log:
springmvc:13 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/font-awesome/4.5.0/css/font-awesome.min.css
springmvc:21 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace.min.css
springmvc:18 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/fonts.googleapis.com.css
springmvc:26 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace-skins.min.css
springmvc:27 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace-rtl.min.css
springmvc:36 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/ace-extra.min.js
springmvc:2149 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery-2.1.4.min.js
springmvc:2159 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/bootstrap.min.js
springmvc:2166 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery-ui.custom.min.js
springmvc:2167 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.ui.touch-punch.min.js
springmvc:2168 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.easypiechart.min.js
springmvc:2169 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.sparkline.index.min.js
springmvc:2170 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.flot.min.js
springmvc:2171 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.flot.pie.min.js
springmvc:2172 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.flot.resize.min.js
springmvc:12 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/bootstrap.min.css
springmvc:18 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/fonts.googleapis.com.css
springmvc:13 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/font-awesome/4.5.0/css/font-awesome.min.css
springmvc:21 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace.min.css
springmvc:26 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace-skins.min.css
springmvc:27 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/css/ace-rtl.min.css
springmvc:36 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/ace-extra.min.js
springmvc:2149 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery-2.1.4.min.js
springmvc:2159 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/bootstrap.min.js
springmvc:2166 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery-ui.custom.min.js
springmvc:2167 GET http://localhost:8080/$%7BpageContext.request.contextPath%7D/resources/js/jquery.ui.touch-punch.min.js
springmvc:2180 Uncaught ReferenceError: jQuery is not defined
at springmvc:2180
Basically, all the lines in my html that has the:
<link rel="stylesheet" href=
Throws an error.
I tried to change the "href" to:
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/ace-skins.min.css" />
But still the same, css, images, etc won't load.
You need to register Resource Handler in spring to serve static content you can do it by XML way as
or
<mvc:resources mapping="/resources/**" location="/resources/" />
Java config
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
you can also add multiple resource location as
.addResourceLocations("/resources/","classpath:/other-resources/");
use commat to delimit the string and you can provide as many resource location as you want!
Enjoy coding!
Try using relative links like below. Also use Thymeleaf's th:href
<link rel="s`tylesheet" type="text/css" media="all"
href="../../../resources/css/styles.css"`
th:href="#{/resources/css/styles.css}" />
See your deployed directory structure and ensure required files are present in said folders (resources)
Remember to change the relative path ../../ to correct level.
If files not being copied to /resources folder then trying putting them in /main/src/webapp/resources
I am struggling with spring mvc file structure.
I am able to display an image ressource in a jsp but not to link a css to it, even if they are at the same location !
Here is my file structure :
/src
/main
/resources
/webapps
/resources
main.css
logo.png
/views
somePage.jsp
/WEB-INF
web.xml
dispatcher-servlet.xml
....
Here is what I have in my dispatcher :
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
And in my somePage.jsp :
<img src="<c:url value="/resources/logo.png" />" alt="blabla" />
<link href="<c:url value="/resources/main.css" />" rel="stylesheet" />
...
The image load correctly but not the css...
Note : I have the following message in eclipse : : "invalid location of tag (link). " about the css link...
If you have any idea, thank you by advance !
Finally it seems to be a cache issue.
I just delete my chrome cache and my css appeared.
When I compiled the first time, my css was empty and I filled it later.
It seems that even after editing it and re-running the project the css state ,wasn't refreshed.
chrome probably kept my css state as empty and didn't detect the update .. weird.
You add some code. like this.
Your servelet-context.xml
<mvc:default-servlet-handler />
Your jsp
<c:set var="contextPath" value="<%=request.getContextPath()%>"></c:set>
<link href="${contextPath}/resources/main.css" rel="stylesheet" />
I'm trying to get Spring 4.1.9 and Thymeleaf 2.1.5 to render XHTML Basic 1.1 pages, which have the following preamble:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
Simply using this in a template doesn't work, as Thymeleaf doesn't recognize the doctype.
org.thymeleaf.exceptions.TemplateProcessingException: Unsupported entity requested with PUBLICID "-//W3C//DTD XHTML Basic 1.1//EN" and SYSTEMID "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd". Make sure a corresponding org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry implementation is provided by you dialect (index:1)
Setup
I went through the Thymeleaf extension documentation and source code and using that as a starting point, defined a new dialect inheriting from SpringStandardDialect. I figured out the missing modules through trial and error, downloading them from w3.org and adding them to the resources directory of my project:
XhtmlBasicDialect.java
import java.util.LinkedHashSet;
import java.util.Set;
import org.thymeleaf.doctype.DocTypeIdentifier;
import org.thymeleaf.doctype.resolution.ClassLoaderDocTypeResolutionEntry;
import org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry;
import org.thymeleaf.spring4.dialect.SpringStandardDialect;
public class XhtmlBasicDialect extends SpringStandardDialect {
private static final String DTD_STANDARD_PATH = "org/thymeleaf/dtd/standard/";
private static final DocTypeIdentifier XHTML_BASIC_11_PUBLICID = DocTypeIdentifier.forValue("-//W3C//DTD XHTML Basic 1.1//EN");
private static final DocTypeIdentifier XHTML_BASIC_11_SYSTEMID = DocTypeIdentifier.forValue("http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd");
private static final DocTypeIdentifier ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ENTITIES XHTML Basic 1.1 Document Model 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_INPUTMODE_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Inputmode 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_TARGET_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Target 1.0//EN");
private static final IDocTypeResolutionEntry XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(XHTML_BASIC_11_PUBLICID, XHTML_BASIC_11_SYSTEMID, DTD_STANDARD_PATH + "xhtml-basic11.dtd");
private static final IDocTypeResolutionEntry ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic11-model-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic-table-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_INPUTMODE_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-inputmode-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_TARGET_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-target-1.mod");
#Override
protected Set<IDocTypeResolutionEntry> getAdditionalDocTypeResolutionEntries() {
final Set<IDocTypeResolutionEntry> docTypeResolutionEntries = new LinkedHashSet<IDocTypeResolutionEntry>();
docTypeResolutionEntries.add(XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY);
return docTypeResolutionEntries;
}
}
I configure the custom dialect as follows:
mvc-config.xml
...
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".xhtml" />
<property name="characterEncoding" value="UTF-8" />
<property name="templateMode" value="XHTML" />
<property name="xhtmlTemplateModePatterns" value="*.xhtml" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="demo.XhtmlBasicDialect" />
</set>
</property>
</bean>
<bean id="xhtmlViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8" />
<property name="contentType" value="application/xhtml+xml" />
</bean>
...
My template is as follows:
DemoTemplate.xhtml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Demo</title>
<link th:href="${'style' + '.css'}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div>
<p>Demo content</p>
</div>
</body>
</html>
The Problem
At first glance, this seems to render fine, except that the resulting XHTML is missing the XML header, and has several extra attributes that are added to every element.
Rendered output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="-//W3C//DTD XHTML Basic 1.1//EN">
<head xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<title xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Demo</title>
<link rel="stylesheet" type="text/css" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve" href="style.css" />
</head>
<body xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">
<p xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">Demo content</p>
</div>
</body>
</html>
This doesn't quite match the XHTML Basic preamable; for one, I would like to keep XML declaration <?xml version="1.0" encoding="utf-8"?>
More importantly, I do not want the xmlns="http://www.w3.org/1999/xhtml", xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance", and xml:space="preserve" attributes to be added to just about every element. There's also an version="-//W3C//DTD XHTML Basic 1.1//EN" attribute added to the <html> element.
Am I doing something wrong, do I need to configure something differently, or am I missing something from the custom dialect?
Well I don't have "canonical" evidence that XHTML Basic templates can't be handled the way you want with Thymeleaf 2.x, and there probably is a way given enough effort. But I did see that:
XhtmlAndHtml5NonValidatingSAXTemplateParser in Thymeleaf 2.1 looks fishy and no longer exists in Thymeleaf 3.0
The XHTML TemplateMode is now deprecated, along with xhtmlTemplateModePatterns
That all the parsing code in 2.1 had been rewritten in 3.0
This, along with my own struggles to get something working, leads me to believe that the XHTML handling in Thymeleaf 2.X was never fully baked. However, it seems to work just fine in 3.0 with no special effort. Just configure a ViewResolver as follows:
<bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="enableSpringELCompiler" value="true"/>
<property name="templateResolver">
<bean class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".xhtml"/>
<property name="templateMode" value="XML"/>
</bean>
</property>
</bean>
</property>
</bean>
I posted a complete working example on github.
I am trying to verify the open graph meta tag & in our site. Here is the HTML code:
<div class="atg_store_applicationResourceContainer">
</div>
<meta name="robots" content="index, follow" />
<!-- Coming inside regular metadetails-->
<!-- contentKey = -->
<!-- SEOTagID - **** -->
<title>Sectional Living Rooms </title>
<meta name="description" content="Find Sectional Living Rooms that will look great in your home and complement the rest of your furniture." />
<meta name="author" content="EXAMPLE.com" />
<meta name="google-site-verification" content="UscxdOsY5bXX9hk_Y0GILMPvzsL66vDcHHwkZZ7Gxpg" />
<meta property="og:title" content="Sectional Living Rooms "/>
<meta property="og:site_name" content="EXAMPLE"/>
<!-- requestSocialUrl = http://www.example.com/cartridges/PageSlot/PageSlot.jsp -->
<!-- customCanonical = http://www.example.com/furniture/Living-Rooms/Sectional-Living-Rooms/_/N-8wh -->
<link rel="canonical" href="http://www.example.com/furniture/Living-Rooms/Sectional-Living-Rooms/_/N-8wh" /> <!-- add + instead of space in words for SEO -->
<meta property="og:image" content="http:/images/unavailable.gif?$PDP_Cart_Primary_150x150$" />
<meta property="og:type" content="product"/>
<meta property="og:url" content="http://www.example.com/furniture/Living-Rooms/Sectional-Living-Rooms/_/N-8wh"/>
<meta property="og:description" content="Find Sectional Living Rooms that will look great in your home and complement the rest of your furniture. #iSofa #abc"/>
<script>var _adblock=true;</script>
I am trying to get the value of the content attribute from meta tags having the property attribute value as og:title & og:description. Any help would be helpful.
I am able to find get the content of the meta with names but am not able to get the content of <og:title> & <og:description> as the tag does not have a name
We are using both UFT & Selenium Webdriver (Java). So I can use help on any single one.
For Selenium you can go with xpath like
//meta[#property='og:title']
//meta[#property='og:description']
And to get the content use getAttribute() method of the WebElement
WebElement titleEl=driver.findElement(By.xpath("//meta[#property='og:title']"));
String titleContent = titleEl.getAttribute("content");
I have simple Spring configuration
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- Scan for components under this package -->
<context:component-scan base-package="com.osfg.test" />
And my controller is
package com.osfg.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* #author athakur
*/
#Controller
public class TestController {
#RequestMapping(value="/test", method=RequestMethod.GET)
public String welcome() {
return "test";
}
}
And my JSP is
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>OSFG Test Page</title>
<link href="CSS/test.css" rel="stylesheet">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
This configuration works fine (CSS does not get applied though).
So I add
<mvc:default-servlet-handler />
to my Spring configuration and now the page itself stops loading giving 404.
Also surprisingly everything works fine (with CSS) will following config
<mvc:view-controller path="/test" view-name="test"/>
<mvc:default-servlet-handler />
Direct rendering no controller involvement.
I think having a simple configuration for resources will suffice.
<mvc:resources mapping="/resources/**" location="/resources/" />
Looks like I found the issue. Somehow the default-sevlet-handler is overriding the DefaultAnnotationHandlerMapping handler? which is why annotation based handler is failing. Following scenarios worked for me -
Use <mvc:annotation-driven/>. This seems to enable default beans including DefaultAnnotationHandlerMapping So combination of
<mvc:annotation-driven/>
<mvc:default-servlet-handler />
worked.
Explicitly define the handler mapping and handler adapter you need with highest preference (chaining). Spring scans all handler mappings and assigns an order property Integer.MAX (if not explicitly defined) which gives it lowest preference. Then these handler mappings are sorted based on this order. Also if two handler mappings are same it looks like it takes bean which is defined first. So following worked for me -
<mvc:default-servlet-handler />
<bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="0" />
</bean>
<bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
So I am guessing default-sevlet-handler creates it's own handler mapping which overrides the annotation one all being at same preference.