Displaying images from MySQL database in JSF datatable [closed] - mysql

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have MySQL database which stores images in a blob column. I would like to show them in a PrimeFaces <p:dataTable>. How can I achieve this?

You can use <p:graphicImage> to display images stored in a byte[], regardless of the byte[] source (DB, disk file system, network, etc). Simplest example is:
<p:graphicImage value="#{bean.streamedContent}" />
which refers a StreamedContent property.
This has however a pitfall, particularly when used in an iterating component such as a data table: the getter method will be invoked twice; the first time by JSF itself to generate the URL for <img src> and the second time by webbrowser when it needs to download the image content based on the URL in <img src>. To be efficient, you should not be hitting the DB in the first getter call. Also, to parameterize the getter method call so that you can use a generic method wherein you pass a specific image ID, you should be using a <f:param> (please note that EL 2.2 feature of passing method arguments won't work at all as this doesn't end up in URL of <img src>!).
Summarized, this should do:
<p:dataTable value="#{bean.items}" var="item">
<p:column>
<p:graphicImage value="#{imageStreamer.image}">
<f:param name="id" value="#{item.imageId}" />
</p:graphicImage>
</p:column>
</p:dataTable>
The #{item.imageId} obviously returns the unique idenfitier of the image in the DB (the primary key) and thus not the byte[] content. The #{imageStreamer} is an application scoped bean which look like this:
#ManagedBean
#ApplicationScoped
public class ImageStreamer {
#EJB
private ImageService service;
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
Image image = imageService.find(Long.valueOf(imageId));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
}
}
}
The Image class is in this particular example just an #Entity with a #Lob on bytes property (as you're using JSF, I of cource assume that you're using JPA to interact with the DB).
#Entity
public class Image {
#Id
#GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
#Lob
private byte[] bytes;
// ...
}
The ImageService is just a standard #Stateless EJB, nothing special to see here:
#Stateless
public class ImageService {
#PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}
See also:
Display dynamic image from database with p:graphicImage and StreamedContent

If you are using Richfaces, you can use a4j:mediaOutput component to stream the blob from a bean.
If that's not the case, I'm afraid I'm not familiar with Primefaces. If it doesn't provide any component for that you need a way of generating a URL that points to a servlet that returns the blob. That way you can use h:graphicImage with that auto-generated URL.

Related

How to show a dynamic image in PrimeFaces 6.1 [duplicate]

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.
Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:
<ui:fragment rendered="#{not empty bean.uploadedFile}">
<img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>
public String getImageContentsAsBase64() {
return Base64.getEncoder().encodeToString(imageContents);
}
Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

Factory to return array of IItem from single object

This is a simplified version of the problem i am solving but conceptually equivalent.
This project is using castle windsor and I am trying to keep all factories in the container.
I have a single object that represents data parsed from a text file. After parsing this file I need to write a new text file with 2 line based on data in the original object.
lets say the text file is
Some Person, Work Phone, Mobil Phone
this gets parsed into
public class Person
{
public string Name{get;set;}
public stirng WorkPhone {get;set;}
public stirng MobilPhone {get;set;}
}
Now this is a simplified example so keep that in mind please. The next step is to creat new object instances that represent each line we will write to the text file
public interface IFileEntry
{
string Name{get;set;}
string Number{get;set;}
}
public class PersonWorkPhoneEntry : IFileEntry
{
public string Name {get;set;}
public string Number{get;set;}
public override ToString(){....}
}
public class PersonMobilPhoneEntry: IFileEntry
{
public string Name{get;set;}
public string Number{get;set;}
public override ToString(){....}
}
so being that we are using Castle for this lets make a factory
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
}
I have created my own implementation for the DefaultTypedFactoryComponentSelector and install that for this factory only.
public class FileEntryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
{
if (method.Name == "Create" && arguments.length == 3)
{
return (string)arguments[0];
}
return base.GetComponentName(method, arguments);
}
}
This works,
var workEntry = _factory.Create("PersonWorkPhoneEntry", person.Name, person.WorkPhone)
var mobilEntry = _factory.Create("PersonMobilPhoneEntry", person.Name, person.WorkPhone)
//then write the tostring to a text file
Sorry for the long setup but i think its needed. What I am trying to do Is
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
IFileEntry[] Create(Person person)
}
var entries = _factory.Create(person);
foreach(var e in entries)
///write to text file.
I have been digging all over for a solution like this with no results.
What seems to be a possible solution taking the example shown here (Castle Windsor Typed Factory Facility with generics)
Im currently working on implementing something like this now, not sure if this is the right way to solve this problem.
The questions:
are there any other ways to have the factory return the array of
needed objects
what is the best practice for solving something like
this
any examples and reading for advanced factories
It is possible to make a Factory return to you an array of objects which are already registered in the container. Here is an example
container.Register(Component.For<IMyStuffProvider>().AsFactory()) // registration
public interface IStuffProvider
{
IEnumerable<IMyStuff> GetAllStuff();
void Release(IMyStuff stuff);
}
This code makes possible that every registered implementation of IMyStuff gets returned by the factory.
But I think that your problem is different : you are using the factory for the wrong purpose. TypedFactory is to get instances of objects that are already registered in the container during app start and not to manipulate files. Their purpose is to solve problems regarding dependencies.
If you are parsing a csv/txt into objects and then writing some of the rows back into another csv/txt you have to make
IFileEntryManager (with an implementation) with a methods like DeserializeFileToObjects, WriteObjectsToFile, etc.
IFileEntryManagerFactory to create and return IFileEntryManager. ( Castle typed factory here :) )
Now inject your IFileEntryManagerFactory in your ctor of the class that needs to serialize/deserialize text files and and use it to get your FileEntryManager which in turn will act upon your text files.
If you have different objects like Person, Company, Employee... etc. and you want to handle them with generic manipulator - it is ok. The best way is to implement a Generic Repository. Lets say ICsvRepository<T>. Just search for 'Generic Rpository in c#' and ignore that fact that most of the implementation examples are with EntityFramework as a persistence store. Behind the interface you can make it read/write to csv rather than to DB.
Lets generalize it. If you have to deal with resources - files, sql, blobs, tables, message bus or whatever resource persistent/non persistent which comes in or goes out of your application you have to manipulate it through an abstraction IMyResourceManager with its corresponding manipulation methods. If you have several implementations of IMyResourceManager and you want to decide during runtime which implementation you want then you have to make IMyResourceManagerFactory with a component selector or factory method and place your differentiation logic there.
That is why I think you do not need a TypedFactory for text file read/write but a pure ITextFileManipulator which you have to register in the container and get it through constructor. You may need a typed factory if you go for ICsvRepository<T> where T is your Person class. Inside the implementation of ICsvRepository<T> you will need ICsvFileManipulator.

not able to integrate gauge.js with jsf page(primefaces)

I want to use gauge.js with my jsf(primefaces) application. I dealt with primefaces components (for which, doesn't require integration) so far. Now, I want to access class property (probably through Json response) from jsf page for generating gauage. I read a solution which suggests to generate json Response but I didn't get it properly. jsFiddle by bernii shows that it requires a dynamic value for creating gauge.
<------sampleClass------>
public int func(){
return aValue; }
<-----JSF----->
<canvas id="gauge"></canvas>
<------Script----->
var gaugeTarget = document.getElementById('gauge');
var gauge = new Gauge(gaugeTwoTarget);
gaugeTwo.maxValue = 100;
gaugeTwo.set(); //how can i get value return by func() here...........
Also BalusC wrote awesome article on it(Java/JSP/JSF and JavaScript). Again m not able to implement it.
Thanks
I missed that part in your question regarding the other solution...
Anyway you can also solve it with a hidden field in your page...
Bean (your bean clas)
int theValue;//add getter and setter
#PostConstruct
public void init(){
theValue = func();
}
Page (your xhtml)
<h:inputText id="myFuncValueId" value="#{myBean.theValue}" style="display:none"/>
js
gaugeTwo.set(document.getElementById('myFuncValueId').value);

CDI conversation and primefaces wizard component

I just realized that my wizard component forgets the steps that lay in the past as I'm using a #RequestScoped wizard backing bean. Using #SessionScoped will work but is ugly.
Thus I tried to get it working using #ConversationScoped but had to realize some strange effect. (maybe out of J2EE experience)
Given this kind of wizard backing bean:
#Named
#RequestScoped
public class EvaluationWizard implements Serializable {
...
#Inject
private Conversation conversation;
#Inject
private Song selectedSong;
...
public void setSelectedSong(final Song song) {
selectedSong = song;
}
public Song getSelectedSong() {
return selectedSong;
}
public void onDialogOpen(final ActionEvent actionEvent) {
conversation.begin();
}
public void onDialogClose(final CloseEvent closeEvent) {
conversation.end();
}
...
}
My Song object looks like this:
#Named
#ConversationScoped
public class Song extends SelectItem implements Serializable {
private String title;
public void setTitle(final String title) {
this.title = title;
}
#Override
public String toString() {
return title;
}
}
The wizard contains several steps in order to set things up. The selectedSong property is an item of a list and represents the currently selected song.
This selection is saved in the "EvaluationWizard" backing bean and my debugging confirms that this is the case - but it's only the case for one wizard step.
Any help on that would be very appreciative.
Greetings, Marcel.
The Primefaces wizard component will not work with RequestScoped beans you are correct. You must either use #SessionScoped or #ViewScoped.
I personally like using ViewScoped as the bean will be created when you navigate to the page and will die when you leave the page. This gives you the benefit of a persisted bean without cluttering up the session.
Yes #RequestScoped won't work. Until today we also used #SessionScoped. Today I learned that it's better to use #ViewAccessScoped because you get window isolation compared to #SessionScoped. In our App we got a lot of bugs caused by #SessionScoped. I just replaced it with #ViewAccessScoped and I solved 17 different tickets in 10 minutes with it.

ErrorProvider(from Windows Forms) for ASP.net & linq-to-sql?

I am trying to figure out how to notify the user which field failed to validate.
I setup LINQ to SQL class datacontext to access a database from ASP.net pages. Since user input will be from by web interface forms and import from Excel files, i would like the write the validation logic in one place. The idea behind this is when i import from excel. I will collect the error messages for each row, and display a summary, somehow. A logical place seems to extend the class generated by LINQ to SQL. According to most documentation and examples, i should do something like this:
public partial class Customer
{
partial void OnTitleChanging(string value)
{
if (!Char.IsUpper(value[0])) {
throw new ValidationException(
"Title must start with an uppercase letter.");}
}
}
The problem with this approach is that validation will stop on the first failed field.
In Windows Forms Link1, if I define an ErrorProvider component in the form and set the DataSource property of it to your BindingSource the exception will be indicated by a red circle right to the validated control. The tooltip of this red circle will show the exception message.
Is there something similar for ASP.net pages? I am using the listview control and inline editing in the listview.
Updates:
- I actually did something similar to what Nick Carver is suggesting. Link2 . Instead of throwing an exception, i record an error message.
public partial class PQSSClassesDataContext
{
public partial class ErrorFeilds
{
private static List<string> Messages = new List<string>();
public void AddErrorMessage(string message)
{
Messages.Add(message);
}
public List<string> GetErrorMessages()
{
return Messages;
}
}
}
I am actually stuck on how to map the error message to the field. That's why i was looking for something like ErrorProvider. I am already using events instead of exceptions to record errors. Any idea how to mark the corresponding failed field from the codebehind file?
Any help appreciated.
What we have done in the past is simply have an error collection on the DataContext, extend it just adding something like a List<ValidationError>. Then all you need to do is override SubmitChanges() and check if you have any validation errors, and decide to abort, throw them, handle however you wish really at that point...all before calling base.SubmitChanges()
We're in a ASP.Net per-request life-cycle, but if your Context is around longer make sure to clear the error list.
It's handy for your ValidationError class/objects to contain a reference to a common base or interface that all your classes implement so you can point to the object later from the error if needed. (e.g. get the ID for throwing the error labels or other info in the right place).
Example classes:
public class ValidationError {
public string Message { get; set; }
public IBase { get; set; }
}
public interface IBase {
public long ID { get; set; }
public DateTime DateModified { get; set; }
}
There is the ValidationSummary control, that works with the individual validation controls to show a list of errors. But the action of the WinForms ErrorProvider is performed in ASP.NET by the individual validation controls, which derive from the Label control