JSF 2.2.10 file upload not working [duplicate] - file-upload

This question already has an answer here:
Upgrade JSF / Mojarra in JBoss AS / EAP / WildFly
(1 answer)
Closed 5 years ago.
Issue: Action method and setter for file not getting called on file upload.
I did see the link for JSF 2.2 not working, but it is over 4 years old and I thought the problem should have been resolved. I am posting this since I am facing it today!
I am using JSF 2.2.10, JBoss 6.4; I have mojarra set up in JBoss config as follows: (in \modules\system\layers\base\org\jboss\weld\core\main and \modules\system\layers\base\org\jboss\as\weld\main)
I have set up my xhtml and Controller as follows. Would greatly appreciate if you could point out what I am missing. Been stuck with this for more than a day now!
<h:form id="massUpload" enctype="multipart/form-data">
<div class="col-xs-3 col-md-3">
<h:inputFile id="file" value="#{controller.uploadedFile}" />
<h:commandButton value="Upload"
action="#{controller.massUploadBranchGLInfoViaFile}"/>
</div>
</h:form>
Controller As follows:
#Named("controller")
#ViewScoped
public class MyController
extends AccessController
implements Serializable
{
private Part uploadedFile;
public String massUploadBranchGLInfoViaFile() throws IOException {
InputStream stream = uploadedFile.getInputStream();
addSuccessInfoToFlash("update-gl-success");
return "Success";
}
public void setUploadedFile(Part file){
this.uploadedFile = file;
}
public Part getUploadedFile(){
return this.uploadedFile;
}
}
Thank you very much
Karthik

Found (at least part of) the issue: Had to add the multipart-config to servlet configuration in my web.xml. That resolved calling the action and set methods. Am getting a NULLPointerException now. But one issue at a time I guess :)

Related

How do I get the Web Root Path and the Content Root Path in ASP.NET Core?

I am trying to add a root path as a parameter in a View, so I can pass it as a parameter to a PayPal button.
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
... snip ...
<input type="hidden" name="return" value="#Model.UrlRoot/Manage/Subscription?userId=#Model.User.Id">
... snip ...
</form>
I was sifting through the answers at
How can I get my webapp's base URL in ASP.NET MVC? (20 answers)
and
ASP.NET MVC 6 application's virtual application root path
Since ASP.NET Core is quite different, the Request class no longer contains a .Url property, so most of those answers don't work.
You can inject the IHostingEnvironment into the Controller like this:
public class HomeController : Controller
{
protected readonly IHostingEnvironment _hostingEnvironment;
public HomeController(IHostingEnvironment hostingEnvironment)
{
}
}
In your _ViewImports.cshtml add:
#using Microsoft.AspNetCore.Hosting
#inject IHostingEnvironment HostingEnvironment
Now you can use can use HostingEnvironment and all its properties in your form.
For example HostingEnvironment.WebRootPath or HostingEnvironment.ContentRootPath
I came across Marius Schulz's post. (If you are Marius, please add your answer, contact me and I'll remove mine.)
https://blog.mariusschulz.com/2016/05/22/getting-the-web-root-path-and-the-content-root-path-in-asp-net-core
For some reason my Controllers don't have the IHostingEnvironment injected in the constructor, but they do have the Request object.
In my Controller, I've declared
var urlRoot = $"{Request.Scheme}://{Request.Host}{Url.Content("~")}";
and passed it to MyViewModel
var model = new MyViewModel { UrlRoot = urlRoot };
return View(model);
This takes into account http vs. https, port numbers, and hopefully, the site root if the web site is not rooted at /. Since my site is at / I cannot confirm that Url.Content("~") gets the site root.
With .NET core 2.1 the context is automatically injected into views.
The base path of the request which displayed the view can be accessed like this:
#(Context.Request.PathBase)
In a net core 5 razor page, I added the following to the top of the page:
#inject IHostEnvironment hostEnvironment
then further down in my code, I used the following code with success:
string filePath = $#"{ hostEnvironment.ContentRootPath }\wwwroot\assets\img\users\{ user.ID }.jpg";
if (System.IO.File.Exists(filePath))
{
imageURL = $"{ user.ID }.jpg";
}

Swagger api listing is empty

Recently I have configure swagger with one of my project. Its using jersey2 and JAX-WS on tomcat for restful API. I have used following manual to configure
https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
${basepath}/swagger.json response with following
{"swagger":"2.0","info":{"version":"1.0.0","title":""},"host":"localhost:8080","basePath":"/myapi","schemes":["http"]}
Unfortounately it does not contain any api which is under my resource package.
I have tried with the answer of following question
swagger - empty listing with no API
But it didn't help either.
The above answer using com.wordnik.swagger.* package(s)
But with the manual I got io.swagger.* package(s), which doesn't have
JaxrsApiReader class
My assumption is swagger couldn't scan my api list from Resource package.
But could not figure out which configuration or which code snippet I have missed.
Any help?....
It looks like you forgot to mark the rest endpoints with #Api
I had the same issue, I used a different approach that worked for me, by adding information only in my Application class. In case you have one, that might help you:
public class MyApi extends Application {
public MyApi() {
super();
BeanConfig beanConfig = new BeanConfig();
beanConfig.setTitle("MyApi");
beanConfig.setVersion("0.0.1");
beanConfig.setSchemes(new String[]{"http", "https"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/mypath");
//putting only the path to my api unblocked me, I removed "io.swagger.resources"
beanConfig.setResourcePackage("system.organization.api");
beanConfig.setScan(true);
beanConfig.setPrettyPrint(true);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<>();
s.add(MyApis);
//for swagger
s.add(ApiListingResource.class);
s.add(SwaggerSerializers.class);
return s;
}
}
Then, the links of classes with #API annotation appeared in swagger.json
Mostly done with the same manual you used: https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-1.X-Project-Setup-1.5

signalR : /signalr/hubs is not generated

I can get this tutorial to work in a new project, but not in my existing project.
My project is an ASP.Net MVC 4 web application with the following attribute in the web.config file:
<appSettings>
<add key="webpages:Enabled" value="true"/>
</appSettings>
This is because my application is a Single-Page-Application, which uses AngularJS on the client side. The only page in my application is index.cshtml, to which I've added the relevant code for signalR:
<!-- signalR chat -->
<script src="~/Scripts/jquery.signalR-1.0.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.client.broadcastMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
Then I've got the ChatHub.cs file:
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
}
And finally in the global.asax:
protected void Application_Start()
{
RouteTable.Routes.MapHubs();
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
When I run the application, the /signalr/hubs file is not generated. I get a 404 when requesting the file, and it crashes on the line:
chat.client.broadcastMessage = function (name, message) { ....
because chat is null as the previous line did not find chatHub:
var chat = $.connection.chatHub;
Does anyone know what's wrong with my code ?
UPDATE
I have solved my problem by changing the line::
<script src="/signalr/hubs"></script>
to
<script src="~/signalr/hubs"></script>
I have solved my problem by changing the line::
<script src="/signalr/hubs"></script>
to
<script src="~/signalr/hubs"></script>
Also, the reason why /signalr/hubs are not generated is forget to Map SignalR in OWIN Startup Configuration.
public class Startup
{
public void Configuration(IAppBuilder appBuilder){
...
appBuilder.MapSignalR();
...
}
...
In my case, it was because my ChatHub class was not marked public.
I had a similar problem where the hubs file wasn't being generated. It looks like the OP was following the steps here. The way I fixed the problem had to do with the jquery includes. The tutorial I linked below was written with jquery 1.6.4 and jquery-signalr version 2.1.0. When Visual Studio generated the Scripts folder for me, it used jquery version 1.10.2 and jquery-signalr version 2.0.2.
The way I fixed this was simply to edit the index.html file. Note that you can use Chrome's javascript console window Ctrl+Shift+J to see errors.
For me the solution was to reinstall all the packages and restore all the dependecies.
Open nuget powershell console and use this command.
Update-Package -Reinstall
I'll like to add that the signalR Readme file have some note about this issue.
And also if your signalR page is in a PartialView some script should be place in the master page.
Please see http://go.microsoft.com/fwlink/?LinkId=272764 for more information on using SignalR.
Upgrading from 1.x to 2.0
-------------------------
Please see http://go.microsoft.com/fwlink/?LinkId=320578 for more information on how to
upgrade your SignalR 1.x application to 2.0.
Mapping the Hubs connection
----------------------------
To enable SignalR in your application, create a class called Startup with the following:
using Microsoft.Owin;
using Owin;
using MyWebApplication;
namespace MyWebApplication
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Getting Started
---------------
See http://www.asp.net/signalr/overview/getting-started for more information on how to get started.
Why does ~/signalr/hubs return 404 or Why do I get a JavaScript error: 'myhub is undefined'?
--------------------------------------------------------------------------------------------
This issue is generally due to a missing or invalid script reference to the auto-generated Hub JavaScript proxy at '~/signalr/hubs'.
Please make sure that the Hub route is registered before any other routes in your application.
In ASP.NET MVC 4 you can do the following:
<script src="~/signalr/hubs"></script>
If you're writing an ASP.NET MVC 3 application, make sure that you are using Url.Content for your script references:
<script src="#Url.Content("~/signalr/hubs")"></script>
If you're writing a regular ASP.NET application use ResolveClientUrl for your script references or register them via the ScriptManager
using a app root relative path (starting with a '~/'):
<script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>
If the above still doesn't work, you may have an issue with routing and extensionless URLs. To fix this, ensure you have the latest
patches installed for IIS and ASP.NET.
In my case i was missing :
app.MapSignalR();
in public void Configuration(IAppBuilder app) function located in startup.cs
Some advice for those that start scaling out from the get go. In my case I was working on getting a remote client to work and never realized that
A. the tutorial example lists the web app(server) startup in a using statement, after which the web app disposes properly and no long exists.
I got rid of the using statement and keep a reference to the web app
for later disposal
B. the client has a different url than the server. the example relies on them having the same url. the "/signalr/hubs" is an endpoint run by the signalr server, called by the signalr client to get a script of all the hubs the server implements.
You need to include "http://myServerURL/signalr/hubs", rather than making it
relative to the client.
No lies. This tripped me up for a solid 2 weeks, because by some magic the solution worked anyways on my coworker's setup. This caused me to keep looking for IIS settings and firewall settings and CORS settings that must have been blocking the connection on my computer. I scavenged every last stack overflow question I could and the ultimate answer was that I should have just implemented a heartbeat monitor on the web app from the start.
Good luck and hopefully this saves other people some time.
See if Microsoft.Owin.Host.Systemweb nuget package is not installed, and therefore not building the dynamic js lib.
OwinStartup not firing

Glassfish 4, JSF 2.2 and PrimeFaces FileUploadEvent not working together

After upgrading to GlassFish 4 and JSF 2.2 Primefaces FileUploadEvent stop working. With JSF 2.1 it was working with no problem. Everything is working fine except file uploading. Is there something that I am missing?
GlassFish 4
JSF 2.2
PrimeFaces 3.4.2 and 3.5
Commons io version: 2.4
Commons fileupload version: 1.3
Controller side
public void handleFileUpload(FileUploadEvent event) {
System.out.println("HandleFileUpload");
byte[] file = event.getFile().getContents();
newFieldset.setData(file);
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
View
<h:form enctype="multipart/form-data">
<p:fieldset legend="Create new feed" toggleable="true" collapsed="true" >
<p:fileUpload fileUploadListener="#{adminHomeController.handleFileUpload}" style="margin-top: 20px;"
mode="advanced"
update="messages"
sizeLimit="1000000"
multiple="false"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
<p:inputText label="Baslik" style="margin-top: 20px;" required="true" value="#{adminHomeController.newFieldset.legend}" />
<p:editor style="margin-top: 20px;"
value="#{adminHomeController.newFieldset.content}" />
<p:commandButton style="margin-top: 20px;" value="#{msg['common.save']}" update="messages" icon="ui-icon-disk" actionListener="#{adminHomeController.saveFieldset()}"/>
</p:fieldset>
<p:growl id="messages" showDetail="true"/>
</h:form>
I was finally able to figure it out. Commons-fileuploads method parseRequest(httpServletRequest) tries to read the request's inputStream. Since the container already read it, it is empty. So what can be done to solve this? The answer is a bit more complicated than I initially thought it would be. First you will need your own FileUploadFilter which could look like this:
public class FileUploadFilter implements Filter
{
private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadFilter.class);
/*
* (non-Javadoc)
*
* #see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
/*
* (non-Javadoc)
*
* #see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
boolean isMultipart = (httpServletRequest.getContentType() == null) ? false : httpServletRequest.getContentType().toLowerCase().startsWith("multipart/");
if (isMultipart)
{
MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest);
LOGGER.info("File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request");
filterChain.doFilter(multipartRequest, response);
}
else
{
filterChain.doFilter(request, response);
}
}
/*
* (non-Javadoc)
*
* #see javax.servlet.Filter#destroy()
*/
#Override
public void destroy()
{
LOGGER.info("Destroying UploadFilter");
}
Next: Register this filter in your web.xml and remove/replace the Primefaces filter. This should look something like this:
<filter>
<filter-name>FileUpload Filter</filter-name>
<filter-class><YourPackage>.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Unfortunately thats not it. You will need your own MultipartRequest since you have to assemble the list of FileItems by yourself. But Stop. We have to work with the javax.servlet.Part classes which are not compatible with the FileItem. So i wrote a new class which bridges these two. You can find this class here: http://pastebin.com/JcfAYjey
The last piece of the puzzle is the mentioned MultipartRequest which links the PartItem and the FileUploadFilter. I took this class from the Primefaces-Repository and changed it according to out needs (see http://pastebin.com/Vc5h2rmJ). The difference is between lines 47 and 57.
So what do you have to do:
1. Create the three classes FileUploadFilter, MultipartRequest and PartItem
2. Register the FileUploadFilter in your web.xml
3. Enjoy!
PLEASE NOTE: This is not intended as a solve-all-problems solution but a merely a direction you may take in further implementations. The MultipartRequest for example will only work for parts with content-type image/*. You may need to change this.
Feel free to change the code ;) Hope it helps!
EDIT: I forgot to mention one important step. You will additionally need your Own FileIUploadRenderer. The one Primefaces implemented uses an instanceof check to find the MultipartRequest. Since you are now using a different one the import has to be changed. The rest of the class can stay the same (http://pastebin.com/rDUkPqf6). Don't forget to register it inside of your faces-config.xml :
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type>
<renderer-class><YourPackage>.FileUploadRenderer</renderer-class>
</renderer>
</render-kit>
Answer lies in UploadFile getInputstream() method. Don't rely on getContents() method.
This is my simple solution which worked with the below dependencies in glassfish 4
Primefaces 4.0.RC1
jsf 2.2
commons-fileupload 1.3
private byte[] getFileContents(InputStream in) {
byte[] bytes = null;
try {
// write the inputStream to a FileOutputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int read = 0;
bytes = new byte[1024];
while ((read = in.read(bytes)) != -1) {
bos.write(bytes, 0, read);
}
bytes = bos.toByteArray();
in.close();
in = null;
bos.flush();
bos.close();
bos = null;
logger.debug("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
return bytes;
}
getFileContents(getFile().getInputstream());
Try to delete beans.xml (CDI configuration file) and use JSF beans.
I saw on PrimeFaces blog that full JSF 2.2 support will be as of version 4.0.
See 3.5 is missing dependency - so won't launch
I think it's a commons-fileupload issue. When I debug through the code, the PrimeFaces' UploadFilter triggers correctly the commons-fileupload's FileUploadBase.parseRequest method (identically flow when I use GlassFish 3.1.22 or GlassFish 4), but the check on FileItemIterator.hasNext returns false.

Why can't I access managed bean methods from a JSF2 page?

In a <rich:popupPanel /> I have a <rich:fileUpload /> which has a fileUploadListener defined as #{assemblyMB.listener}. This listener method is defined on the managed bean as:
public void listener(FileUploadEvent event) throws Exception {
System.out.println("listener");
}
on the JSF page I have:
<rich:fileUpload id="popupFileUpload"
fileUploadListener="#{assemblyMB.listener}"
onuploadcomplete="#{rich:component('popup')}.hide(); return false;"
</rich:fileUpload>
On the managed bean, I have declared the annotation #ManagedBean(name = "assemblyMB").
I intend to access the method on the managed bean when the file is uploaded, but I'm failing to do so. I don't understand why is that happening.
Can anybody throw me a light here? Thanks in advance,
gtludwig
Assuming RichFaces 4.0, all you need to ensure is that the parent <h:form> is set to encode the request body as multipart/form-data.
<h:form enctype="multipart/form-data">
This way the file should be uploaded properly and the listener method should be invoked when the upload has been arrived in the server side.