How to implement Dart with Spring MVC and Thymeleaf? - spring-mvc

I'm currently trying to implement Dart in an existing project which uses Spring MVC (4.0.0) and Thymeleaf (2.1.1) as template engine.
Currently I am deploying all my Dart resources to /dart as shown belown.
<link rel="import" th:href="#{/dart/wb-control-text.html}" />
<script type="application/dart" th:src="#{/dart/packages/polymer/init.dart}"></script>
<script th:src="#{/dart/packages/browser/dart.js}"></script>
Thymeleaf rewrites the urls to http://localhost:8080/context/dart/..., which is correct.
Dart works really great if you open a HTML file directly which has the packages folder directly beneath it. However, this is not the case in my project, which has friendly urls like /action/users/browse and you don't have access directly to the HTML file.
When a Dart library tries to import a package, I get a 404 error because it is looking for it in the wrong place (e.g. /dart/packages/polymer/packages/polymer/polymer.dart).
Do I need to provide a URL request handler or a filter that handles all **/packages/** requests (and just use paths relative to the current url)? Or is there an option in Dart where you can set where it should look for packages?
What is the solution (or workaround) for this?
Edit
I currently have a temporary solution that works, but it is dirty and I'm still looking for a cleaner solution.
I added the packages to my classpath and I created a DartPackagesFilter that streams the resources:
public class DartPackagesFilter extends OncePerRequestFilter
#Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain filterChain)
throws ServletException, IOException {
final String uri = request.getRequestURI();
final int index = uri.indexOf("/packages/");
if ( index != -1 ){
final String resourceName = uri.substring(index);
writeResourceToResponse(response, resourceName);
return;
}
filterChain.doFilter(request, response);
}
private void writeResourceToResponse(final HttpServletResponse response, final String resourceName) throws IOException {
final ClassPathResource resource = new ClassPathResource(resourceName);
response.setContentType(resolveContentType(resourceName));
ChannelUtils.stream(resource.getInputStream(), response.getOutputStream());
}
private String resolveContentType(final String resourceName){
if ( resourceName.endsWith("dart") ){
return "application/dart";
} else if ( resourceName.endsWith("js")){
return "text/javascript";
}
throw new IllegalArgumentException("Resource must be a Dart or Javascript file!");
}
}
In web.xml:
<filter-mapping>
<filter-name>DartPackagesFilter</filter-name>
<url-pattern>*.dart</url-pattern>
<url-pattern>*.js</url-pattern>
</filter-mapping>
In my HTML file I refer to the packages relatively to the current URL:
<script src="packages/browser/dart.js"></script>

You will need to handle /packages/ requests separately, like your work-around. However, these hacks would only be needed for development when you are working with the actual .dart files.
When you deploy your app, you'll use either dart2js, dart2dart or, most likely, both. These tools produce a monolithic script file which does not rely on the external packages directory.
Since you only need the /packages/ directory for development, it is possible to set the the packages URL through a flag in Dartium. However, in my experience, this is an awkward solution since the flag applies to all Dart applications -- all Dart apps would need to fetch packages through the same URL scheme. It also makes it difficult to share your app with other Dartium installations.

Related

AEM Servlet not getting executed

I have a servlet with OSGI annotation like below
#Component( immediate = true, service = Servlet.class, property = { "sling.servlet.extensions=json",
"sling.servlet.paths=/example/search", "sling.servlet.methods=get" } )
public class SearchSevrlet
extends SlingSafeMethodsServlet {
#Override
protected void doGet( final SlingHttpServletRequest req, final SlingHttpServletResponse resp )
throws ServletException, IOException {
log.info("This is not getting called ");
}
}
But When i try to hit the servlet with JQuery
$.get( "/example/search.json", function( data ) {
$( ".result" ).html( data );
alert( "Load was performed." );
});
I am getting below information rather than servlet getting executed.
{"sling:resourceSuperType":"sling/bundle/resource","servletClass":"com.group.aem.example.servlet.SearchSevrlet","sling:resourceType":"/example/search.servlet","servletName":"com.group.aem.example.servlet.SearchSevrlet"}
Please let me know if i need to make any other configuration.
The info that you are getting is the answer of the Default JSON Servlet
Please read this: Servlets and Scripts
You are registering the "SearchServlet" with the property "sling.servlet.paths". This property is defined as:
sling.servlet.paths: A list of absolute paths under which the servlet is accessible as a Resource. The property value must either be a single String, an array of Strings...
That means that your servlet will be only triggered if you request the same exact path, in this case "/example/search", like this:
GET /example/search
I would recommend you to use the properties "resourceTypes" and "selectors" in your Servlet rather than "paths". For example, a better configuration could be:
property = {
"sling.servlet.resourceTypes=/example/search.servlet",
"sling.servlet.selectors=searchselector",
"sling.servlet.extensions=json",
"sling.servlet.methods=GET"
}
With this config, your SearchServlet should be triggered with a GET request to a resource with resourceType="/example/search.servlet", with the selector "searchselector" and the extension "json". For example:
GET /corcoran/search.searchselector.json
I had a similar problem with yours.
To find out what is wrong, I checked "Recent Requests" page.
(at http://localhost:4502/system/console/requests.)
In my case, there was a log saying, "Will not look for a servlet at (my request path) as it is not in the list of allowed paths".
So I moved to "Config Manager" page(at http://localhost:4502/system/console/configMgr), and searched for "Apache Sling Servlet/Script Resolver and Error Handler".
It has a list named "Execution Paths", and I added my request path to the list.
After adding my path to the list, the problem is solved.

How ImageSharp work with Asp.Net Mvc Controller

How ImageSharp work with Dynamic Images loaded from Database?
Here my controller which get image file:
public async Task<FileResult> GetPhoto([FromQuery] GetFileAttachementInputAsync input)
{
var file = await filesAttachementAppService
.GetFileAsync(new GetFileAttachementInputAsync() { FileId = input.FileId })
.ConfigureAwait(false);
return file != null
? File(new MemoryStream(file.FileDto.FileContent), file.FileDto.ContentType, file.FileDto.FileName)
: null;
}
And this my Html call:
<img src="/PropertyAdministration/GetPhoto?FileId=#item.MainPhotoId&width=554&height=360" alt="" />
I am using ImageSharp as following:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddImageSharp();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
{
app.UseImageSharp();
}
What I am missing here to make this working?
You're not using the middleware nor the services that provide images to the middleware.
For the middleware to work it needs to be able capture an image request. With the default installation this is done by matching the request to an image source in your physical file system in wwwroot.
In your code though you've created an isolated action result returning a stream containing your image which the middleware has no awareness of.
Disclaimer, the following is based on the latest developer build 1.0.0-dev000131 and though unlikely to change could potentially change before final release.
https://www.myget.org/feed/sixlabors/package/nuget/SixLabors.ImageSharp.Web/1.0.0-dev000131
In order to provide images from a custom source you will need to create your own implementation of the IImageProvider and IImageResolver you can use examples in the source to base your implementation from.
Once implemented you will need to register the implementations via dependency injection. This needs to use a more fine grained registration since you are no longer using the defaults.
// Fine-grain control adding the default options and configure all other services. Setting all services is required.
services.AddImageSharpCore()
.SetRequestParser<QueryCollectionRequestParser>()
.SetBufferManager<PooledBufferManager>()
.SetMemoryAllocatorFromMiddlewareOptions()
.SetCacheHash<CacheHash>()
.AddProvider<PhysicalFileSystemProvider>()
/// Add your provider here via AddProvider<T>().
.AddProvider<PhysicalFileSystemProvider>()
.AddProcessor<ResizeWebProcessor>()
.AddProcessor<FormatWebProcessor>()
.AddProcessor<BackgroundColorWebProcessor>();
You should then be able to remove your action result completely and use the IImageProvider and IImageResolver combination to identify the request and return the image.

Error resolving template with Spring Boot using Thymeleaf packaged in a .jar

I have a Spring Boot application using Thymeleaf as template resolver, which works fine when debugging from NetBeans, but gives me this error running its .jar:
Error resolving template "/theme/property", template might not exist or might not be accessible by any of the configured Template Resolvers
The app is set to auto-configurer with the annotation #SpringBootApplication, at an extension of SpringBootServletInitializer. I haven't set any contextPath into the properties file. I'm using Thymeleaf 2.1.6 and Spring 4 version. The jar is generated with Maven.
Doing some research I've come out that in some controllers I was passing a double slash, which I've solved but most pages still not working.
This controller works:
#GetMapping("/{idweb}")
String frontEndHome(#PathVariable("idweb")Integer idweb, Model model){
...
return "theme/home";
With the return statement set as return "/theme/home"; doesn't work. I guess, because the template resolver is recieving a double slash (//).
This other controller raises the error:
#GetMapping("/{idweb}/property")
String frontEndProperty(#PathVariable("idweb") Integer idweb, #RequestParam(value = "idproperty", required = false) Integer idproperty, Model model) throws Exception {
...
return "theme/property";
The index controller works fine as well:
#GetMapping("/")
public String index(Model model){
...
return "index";
}
That's my application starter class:
#SpringBootApplication
public class RentalWebsApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(RentalWebsApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(RentalWebsApplication.class, args);
}
}
For Thymeleaf I haven't set any configuration, although I've tested the app setting this into the application.properties file, with the same result:
spring.thymeleaf.prefix=classpath:/templates/
All html files are set into:
src/main/resources/templates
The html files from the examples are in:
src/main/resources/templates/index.html
src/main/resources/templates/theme/home.html
src/main/resources/templates/theme/property.html
There are some other questions dealing with the same issue, but none has a solution that works for me. Any help, would be much appreciated.
Update
Deploying the jar into Pivotal Web Services, the whole website works fine, but not deploying it with Boxfuse, Heroku or running the jar locally. Therefore, I guess the origin of the problem is some wrong configuration, that Pivotal system detects and corrects.*
*
PWS isn't correcting a configuration problem. It unpacks your jar file before running the application which stops the double slash from causing a problem. – Andy Wilkinson
At the end the solution was related to the double slashes, that the classpath:/templates/ gets if we set a return statement with a slash at the beginning like:
return "/theme/property"
Instead of:
return "theme/property"
In my case, the problem was not at the controller, but in the html with the Thymeleaf references of fragments, like in this example:
<footer th:replace="/index::footer"></footer>
Instead of:
<footer th:replace="index::footer"></footer>
What I don't understand is why the IDE's (NetBeans and STS), where not raising the error.
use
return new ModelAndView("member2",map);
instead of
return new ModelAndView("/member2",map);
Remove spring.thymeleaf.prefix=classpath:/templates/ from your application.properties.

Accessing services directory when setting up Zend AMF in Codeigniter

I followed the instructions in this tutorial to set up Zend AMF as a way of passing data from my flash app to my PHP app:
http://codeigniter.com/forums/viewthread/180414/
So I have the directory structure and everything as described there. This is my gateway controller:
class Gateway extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('zend');
//root_folder + application + controllers + amf + services
define('SERVICES_FOLDER', APPPATH.'controllers/amf/services/');
}
public function index()
{
$server = new Zend_Amf_Server();
$server->setProduction(false);
//$server->addFunction('testservice');
$server->addDirectory(SERVICES_FOLDER);
echo $server->handle();
}
}
And the APPPATH is /application/ so the path defined by SERVIES_FOLDER is "/application/controllers/amf/services" which is where my file 'testservice.php' sits.
When I try and connect to that service in flash:
var gateway:String = "http://mysite.com/amf/gateway";
con.connect(gateway);
con.call("Testservice.getMessage", new Responder(onResult, onFault));
It calls the onFault method and displays the error:
Plugin by name 'Testservice' was not found in the registry;
Which makes me think that the addDirectory() line in Gateway.php was the problem somehow. Interestingly, I also cannot access the testservice function through a URL, ie by going to mysite.com/amf/services/testservice.
Any thoughts on what might be going on here?
Figured it out, sort of.
Instead of using the addDirectory method which I was having no luck with, I used the setClass method and created another class within the gateway.php file that has the functions, and now I can connect to those functions from flash.
I had an issue with this when using parent::__construct() in my service controllers. Once I removed that, the problem went away.

How do I make Flex file upload work on firefox and safari?

I have a flex app that uploads files to a server. The server requires authentication to be able to upload. In IE the upload works fine. However in FF and Safari, it does not upload. I have seen people all over with this same problem but no answers. Don't fail me now stackoverflowers.
I found this question while trying to find the answer myself. The solution was rather simple.
Based on the flash player bug that others have linked, and the comments on that page, I decided to append session identifiers to my upload URL and give it a shot. It really was that easy!
To make it work, I started by adding a flashVar parameter called sessionParams. This allowed me to pass any string I want in to the flash player as my session identifier, and it will later get appended to the URL used to upload.
//sessionParams - resolves firefox upload bug
public var sessionParams:String = "";
//...
public function initApp():void{
sessionParams = Application.application.parameters.sessionParams;
}
In my case, I'm on ColdFusion with java sessions enabled, so my sessionParams are setup like the following before being passed into the flash player:
<cfset flashVars = "sessionParams=#urlEncodedFormat('jsessionid=' & session.sessionid)#" />
Don't forget to escape special characters like =,&, etc (which I've done with urlEncodedFormat), so that they are treated as part of the value of the "sessionParams" parameter, and not breakpoints to indicate other parameters. You're embedding future-URL information in the current URL.
Then, use the sessionParams value in your upload code. Here's a snippet of how I set mine up:
// Set Up URLRequest
_uploadURL = new URLRequest;
_uploadURL.url = _url + "?" + _sessionParams;
_uploadURL.method = "GET";
_uploadURL.data = _variables;
_uploadURL.contentType = "multipart/form-data";
The variable names are different (but similar) because this is part of a reusable class.
Hopefully that helps you. If not, let me know and I'll try to provide more code or explanation to help you out.
The problem at least in Firefox is that the session cookies are not sent in the request when you invoke FileReference.upload(). What you need to do is add the authentication token either as a form variable or in the query string. Here is an example in Java where the session cookie is called "jsessionid"
var request : URLRequset = new URLRequest( uploadUrl + ";jsessionid=" + jsessionid);
You can parse the jsessionid out of cookies using Javascript and ExternalInterface to invoke the Javascript function. Or after you authenticate you can have Flex call a backend method that returns the current sessionID.
The related Flex bug is here:
http://bugs.adobe.com/jira/browse/FP-201
I solved this problem. File upload using flex will work on all the browsers.In J2ee application,
comment the security-constraint or make the fileupload.do URL unprotected in web.xml where you will put the actual code.
<security-constraint>
<display-name>Senusion Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Un Protected Area</web-resource-name>
<url-pattern>/fileupload.do</url-pattern>
</web-resource-collection>
</security-constraint>
Hope this will help the next reader.
FlashPlayer 10 provides a new Filereference API that can help a lot.
Here is a blog entry that describes it : http://www.flexpasta.com/index.php/2010/02/21/uploading-files-with-firefox-solution/.
Indeed in Flash 10 an enhancement to flash.net.FileReference makes it possible to read the contents of a file before it is uploaded. Meaning that the file can be uploaded in different ways then can be done in Flash 9. The following example shows how easy file uploading can be and is not tied to SSL, Firefox, IE, Chrome, etc.
i managed to work around this bug using flex and java web filter
Flex Code :
var urlVars:URLVariables = new URLVariables();
urlVars.jsessionid = sessionID;
var uploadUrl:String = "http://localhost:8080/mywar;jsessionid="+sessionID;
uploadUrl += "?"+getClientCookies(); //put all client cookies on the query string
var urlRequest:URLRequest = new URLRequest(uploadUrl);
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = urlVars;
//will go first time and get the cookies set see flex docs
var testUpload:Boolean = true;
fileRef.upload(urlRequest,"Filedata",testUpload);
JAVA CODE :
package com.mywar.fileupload;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* #author orasio - spieler
* This filter comes to solve the Firefox ,Chrome and SAFARI file upload issue
* The problem was that the file uploaded by the flex
* FileReference came with a different session and no cookies
* To solve this problem do the following :
*
*
* don't forget to add this filter to the web.xml file
*/
public class FileUploadFilter implements Filter {
private static final String CONTENT_LENGTH = "content-length";
private static final String UPLOAD_SITE_PATH = "/";
private static final String JSESSIONID = "JSESSIONID";
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse)) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
//httpRequest.getHeader("user-agent"); //Shockwave Flash
String contentLength = httpRequest.getHeader(CONTENT_LENGTH);
boolean isFlexTest = (contentLength!=null
&& Integer.parseInt(contentLength)==0);
if(isFlexTest){
HttpServletResponse httpResponse =
(HttpServletResponse) response;
setAllClientCookie((HttpServletResponse)response, httpRequest);
PrintWriter out = httpResponse.getWriter();
out.println("OK");
out.close();
return;
}
}
filterChain.doFilter(request, response);
}
/*
* write all cookies back to the flex test response
*/
#SuppressWarnings("unchecked")
private void setAllClientCookie(HttpServletResponse httpResponse,
HttpServletRequest httpRequest) {
Enumeration<String> parameterNames =
(Enumeration<String>)httpRequest.getParameterNames();
while (parameterNames.hasMoreElements()) {
String cookieName = (String) parameterNames.nextElement();
//since we get IllegalArgumentException: Cookie name "JSESSIONID" is a reserved token
if(!cookieName.contains(JSESSIONID)) {
Cookie cookie =
new Cookie(cookieName, httpRequest.getParameter(cookieName));
cookie.setPath(UPLOAD_SITE_PATH);
httpResponse.addCookie(cookie);
}
}
}
#Override
public void destroy() {
}
}
I faced the same issue.. File upload was working on all browsers except firefox. In firefox, error#2038 was being thrown while uploading file. The application used SSL..
In my case, even the upload request wasn't being generated from firefox which I could confirm by seeing in firebug's Net panel, the upload URL was not being hit. That means, may be flash runtime in firefox was blocking the upload request.
However, when I ran application in IE, installed the self signed certificate of the application in IE, file upload ambigously and ofcourse amazingly, started working in firefox..
So first please check whether request is even being reached to the server or getting blocked at the client.
Thanks
Looks like this is quite old, but I recently ran into this problem, too. My fix (which is far from optimal) under a Flex + authenticated rails setup was to turn off the session based authentication on the upload script.
Since I really did want at least basic authentication, I stored the username and password that the user logged in with, and wrote the code to send/validate that manually on the rails side. I could never get the "jsessionid" hack to work, as flash doesn't have access to the browser sessions.
I hope this helps someone save a bit of time.
This is an actual flash player bug. Maybe this link will give you some ideas.
What do you have on the server side? Maybe you could add the sessionid as a parameter in your request.
Some times even if we send the cookies through the URL it will not work. This is because the Flex is blocking the file upload request.
To unblock it you have to install the SSL certificate, and then try it.
If any one has any other answer please let me know.
Since I was building a Flash App for Facebook, I had no access to jsessionid.
I solved this problem by uploading to a HTTPS address instead of HTTP.
One thing that caused me trouble is that in OSX Firefox and Safari (not Chrome), the (FileReferenceInstance).type is null, and the (FileReferenceInstance).name comes with the full extension (myimage.jpg).

Resources