Thymeleaf at syntax: "#{/}" returns empty if I include ResourceUrlEncodingFilter - spring-mvc

I'm using Thymeleaf.
This template:
<a th:href="#{/}">a</a>
produces this html:
a
This is what I'm expected.
I put ResourceUrlEncodingFilter bean to try ContentVersionStrategy in my WebMvcConfigurerAdapter extended class.
#Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
The produced html turned to:
a
The value of href is empty.
I hope href is "/" even if I put ResourceUrlEncodingFilter bean.
th:href="#{/a}" turns to href="/a" in both cases.
Did I do something wrong?
Thank you very much.
UPDATE:
This is my build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE'
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
apply plugin: 'io.spring.dependency-management'
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
}
}
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom 'io.spring.platform:platform-bom:1.1.2.RELEASE'
}
}
dependencies {
compile('org.webjars:bootstrap:3.3.1')
compile('org.webjars:knockout:3.2.0')
compile('org.webjars:momentjs:2.9.0')
compile('org.webjars:numeral-js:1.5.3-1')
compile('org.webjars:underscorejs:1.7.0-1')
compile('org.webjars:sugar:1.4.1')
compile('org.webjars:jqplot:1.0.8r1250')
compile('org.webjars:jquery-cookie:1.4.1-1')
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-batch")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-tomcat")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-test")
compile("org.springframework:spring-context-support") // this is for mail
compile('commons-codec:commons-codec')
compile("commons-io:commons-io")
compile('com.google.guava:guava')
compile('org.hibernate:hibernate-validator')
compile("com.sun.mail:javax.mail")
compile('mysql:mysql-connector-java')
compile("org.yaml:snakeyaml")
compile("org.apache.commons:commons-lang3:3.2")
compile('com.amazonaws:aws-java-sdk:1.9.4')
compile('net.sf.supercsv:super-csv:2.2.0')
compile('edu.vt.middleware:vt-password:3.1.2')
}
test {
//systemProperties 'property': 'value'
systemProperties 'spring.profiles.active': 'unittest'
systemProperties 'MAIL_PROP': 'mail.properties'
systemProperties 'user.timezone': 'UTC'
}
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}

Thanks for this detailed explanation and the repro project!
This is actually a bug: see SPR-13241, to be fixed in Spring 4.1.8 and 4.2.0.

Spring Boot adds "/**" matcher for automatic configurations of static web resources locations.
The locations are /META-INF/resources/, /resources/, /static/ and /public/.
When you put below html in Thymeleaf template,
<a th:href="#{/}">a</a>
Below method in ResourceUrlProvider.java is called because of the matcher and get into for loop:
public final String getForLookupPath(String lookupPath) {
// -- omission --
for(String pattern : matchingPatterns) {
// -- omission --
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(pattern, lookupPath);
String pathMapping = lookupPath.substring(0, lookupPath.indexOf(pathWithinMapping));
// -- omission --
String resolved = chain.resolveUrlPath(pathWithinMapping, handler.getLocations());
if (resolved == null) {
continue;
}
// -- omission --
return pathMapping + resolved;
}
// -- omission --
}
The argument, lookupPath is "/" by the "#{/}", Then:
The pathWithinMapping will be "".
The pathMapping will be "".
The resolved will be "".
So this method returns "" and the value is set to href="".
This is in my opinion, if the pathWithinMapping is "", to continue the for loop seems good. Calling chain.resolveUrlPath seems not good.
Thanks,

Related

gradle plugin copy without default excludes

I want to get some dependency artifact and copy the content into a specific location.
This works well in general, but not for files called e.g. .gitignore.
I found that those are default excludes.
How can i disable those default exclude, by using the Java-Gradle-API in my plugin code?
project.copy( spec -> {
spec.from (project.zipTree(artifact.getFile()));
spec.into( tf.toFile());
//spec.setExcludes(Collections.emptyList()); // does not work
});
Also i tried to the setExcludes in the from/into copyspec.
Frank
I found a solution, but i don't like it, because it modifies the globally visible defaultExcludes:
private static void withoutDefaultExcludes( Runnable r ) {
String[] defaultExcludes = org.apache.tools.ant.DirectoryScanner.getDefaultExcludes();
try {
for( String defaultExclude : defaultExcludes) {
org.apache.tools.ant.DirectoryScanner.removeDefaultExclude(defaultExclude);
}
r.run();
}
finally {
for( String defaultExclude : defaultExcludes) {
org.apache.tools.ant.DirectoryScanner.addDefaultExclude(defaultExclude);
}
}
}
withoutDefaultExcludes( () -> {
project.copy( spec -> {
spec.from (project.zipTree(artifact.getFile()));
spec.into( tf.toFile());
});
});

Eclipse LTK refactoring - Resources path not being updated when project is renamed

I am writing custom refactoring for renaming project/folder/file in Eclipse RCP application. I have extended the Refactoring class and wrote my own ResourceChange class where I am updating the project resources by calling IProject.move() method.
The rename is working fine but path of the resources under the project are not updated.
Any pointers will be helpful.
Thanks.
Update:
Refactoring class Code:
#Override
public Change createChange(IProgressMonitor pm) {
pm.beginTask("Renaming", 1);
CompositeChange change = new CompositeChange("Renaming");
if(resource instanceof IProject) {
return new CustomResourceChange((IProject)resource, resourceName);
}
pm.done();
return change;
}
CustomResourceChange class code:
protected IPath createNewPath() {
return modifiedResourcePath.removeLastSegments(1).append(resourceNewName);
}
#Override
public Change perform(IProgressMonitor pm) throws CoreException {
try {
pm.beginTask("Renaming Project", 1);
Change change = new CustomResourceChange(modifiedResource, createNewPath(), resourceOldName, resourceNewName);
IProject project = (IProject)ResourcesPlugin.getWorkspace().getRoot().findMember(modifiedResourcePath);
if (project != null) {
IProjectDescription description = project.getDescription();
description.setName(resourceNewName);
project.move(description, IResource.FORCE, new SubProgressMonitor(pm, 1));
}
return change;
} finally {
pm.done();
}
}

How to access global telerik functions in typescript

I try to access the function GetRadWindowManager() from my app.ts file.
I added the definitions files and I cannot find a way to call "window.GetRadWindowManager()" or "window.top.GetRadWindowManager()"
That is my code until now :
export class App {
private _windowManager: Telerik.Web.UI.RadWindowManager;
constructor() {
this._windowManager = null;
}
getRadWindowManager(): Telerik.Web.UI.RadWindowManager {
if (this._windowManager == null) {
try {
this._windowManager = window.top.GetRadWindowManager();
} catch (err) {
this._windowManager = GetRadWindowManager();
}
}
return this._windowManager;
}
}
PS : Don't mind the try/catch block, I'll remove that later :)
Thanks for your help !
Well, I don't know if this answer is the best, but extending the Window object allowed me to manually add this function. Then I can simply call it from my script.ts
interface Window {
GetRadWindowManager(): Telerik.Web.UI.RadWindowManager;
}

Symfony2 OOP design

I'm facing a OOP design problem ... My goal is to build a Improvement system.
It is really simple to understand, here is the code sample :
<?php
interface Improvement {
public function getGains();
public function isActivated();
}
// tagged "improvement"
class AImprovement implements Improvement {
public function getGains() {
return 1;
}
public function isActivated() {
return true;
}
}
// tagged "improvement"
class BImprovement implements Improvement {
private $statsCenter;
public function __construct(StatsCenter $statsCenter) {
$this->statsCenter = $statsCenter;
}
public function getGains() {
return 10;
}
public function isActivated() {
return $statsCenter->getStats()['totalGains'] > 10;
}
}
class ImprovementCenter {
private $improvements;
public function addImprovement(Improvement $improvement) {
$this->improvements[] = $improvement;
}
public funtion getGainsSum() {
$s = 0;
foreach ($this->improvements as $improvement) {
$s += $improvement->getGains();
}
return $s;
}
}
class StatsCenter {
private $improvementCenter;
public function __construct(ImprovementCenter $improvementCenter) {
$this->improvementCenter = $improvementCenter;
}
public function getStats() {
return [
'totalGains' => Money::toEUR($this->improvementCenter->getGainsSum())
];
}
}
We can create x implementations of Improvement interface. If we tag them with "improvement" they will be added to the definition of ImprovementCenter with addMethodCall by calling addImprovement.
So, ImprovementCenter has a clear dependency on all the "improvement" tagged services.
And for some reason BImprovement is enabled only if the gains in euros > 10. ( Don't ask me why ).
But we can clearly see a circular dependency : BImprovement -> StatsCenter -> ImprovementCenter -> BImprovement ...
Any ideas on how to solve it ? (I already found some solution but I need more ideas). The side goal is also to benefits lazy services loading of symfony2, ImprovementCenter must be created only if it is injected somewhere.
Thank you !
EDIT :
Here is one dirty solution that I found. First the main problem is that here I have an observer pattern with Improvements as Observers. The consequence is that ImprovementCenter (the subject) depends on all its observers, that is not the pattern goal.
Then I moved the dependencies: I have kind of an ObserverManager that depends on ImprovementCenter and all Improvents, the ObserverManager manually do $improvementCenter->addImprovement($improvement).
Now the $improvementCenter has no dependency on Improvements.
The problem is that I must initialise ObserverManager on each kernelRequest, without that trick the ImprovementCenter will not have any Improvements linked as observers.
This solution perfectly works, but it smells kind of bad .. ahah
Ideas ?

Swashbuckle rename Data Type in Model

I'm putting together a web API that needs to match an external sources XML format and was looking to rename the Data Type objects in the swagger output.
It's working fine on the members of the class but I was wondering if it was possible to override the class name as well.
Example:
[DataContract(Name="OVERRIDECLASSNAME")]
public class TestItem
{
[DataMember(Name="OVERRIDETHIS")]
public string toOverride {get; set;}
}
In the generated output I end up seeing
Model:
TestItem {
OVERRIDETHIS (string, optional)
}
I'd hope to see
OVERRIDECLASSNAME {
OVERRIDETHIS (string, optional)
}
Is this possible?
Thanks,
I had the same problem and I think I solved it now.
First of all add SchemaId in Swagger Configuration (from version 5.2.2 see https://github.com/domaindrivendev/Swashbuckle/issues/457):
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SchemaId(schemaIdStrategy);
[...]
}
Then add this method:
private static string schemaIdStrategy(Type currentClass)
{
string returnedValue = currentClass.Name;
foreach (var customAttributeData in currentClass.CustomAttributes)
{
if (customAttributeData.AttributeType.Name.ToLower() == "datacontractattribute")
{
foreach (var argument in customAttributeData.NamedArguments)
{
if (argument.MemberName.ToLower() == "name")
{
returnedValue = argument.TypedValue.Value.ToString();
}
}
}
}
return returnedValue;
}
Hope it helps.
Pretty old question, but as I was looking for a similar solution, I bumped into this.
I think the code in Vincent's answer might not work.
Here is my take on it:
private static string schemaIdStrategy(Type currentClass)
{
var dataContractAttribute = currentClass.GetCustomAttribute<DataContractAttribute>();
return dataContractAttribute != null && dataContractAttribute.Name != null ? dataContractAttribute.Name : currentClass.Name;
}
Adding to the thread as I am not able to use the answer with Swashbukle for AspNetCore.
I am doing this. However I am not totally happy as if the object is contain in another object it is showing its original name. For example if you have a result set that is Paged That result is shown incorrectly.So this is not a final answer but might work on simple use cases.
I am using a Schema Filter. And the object just have [JsonObject(Title="CustomName")] as I get the Title property for the data type.
First Define a class like this:
public class CustomNameSchema : ISchemaFilter
{
public void Apply(Schema schema, SchemaFilterContext context)
{
if (schema?.Properties == null)
{
return;
}
var objAttribute = context.SystemType.GetCustomAttribute<JsonObjectAttribute>();
if( objAttribute!= default && objAttribute?.Title?.Length > 0)
{
schema.Title = objAttribute.Title;
}
}
}
On the startup you must configure a SchemaFilter
c.SchemaFilter<CustomNameSchema>();

Resources