Kamis, 25 Desember 2014

OmniFaces 2.0 released!


OmniFaces 2.0 has been released!



The minimum requirements have been upgraded from Java 1.6, JSF 2.0, EL 2.1 and Servlet 2.5 to Java 1.7, JSF 2.2, EL 2.2, Servlet 3.0 and CDI 1.1. An important change is thus that the optional CDI dependency is now required. OmniFaces 2.0 won't deploy on an environment without CDI. This way we can keep things simple and move forward.



As of now, OmniFaces 2.0 is still fully backwards compatible with JSF 2.1, but not with JSF 2.0 anymore. OmniFaces 2.0 is also backwards compatible with CDI 1.0, as long as you don't use the Beans#destroy() utility method which works only in CDI 1.1. Noted should be that future 2.x versions may not be backwards compatible with either JSF 2.1 or CDI 1.0 anymore, so don't take the backwards compatibility of 2.0 as a guarantee for the same in future 2.x versions.



As usual, in the What's new page of the showcase site you can find an overview of all what's been added/changed/fixed for 2.0. The top three additions which will likely become popular are the taghandler, component and @Param annotation. Do however check out the What's new page for more, with among others the NoAutoGeneratedIdViewHandler and the which Arjan Tijms blogged about.




Installation



Non-Maven users: download OmniFaces 2.0 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.



Maven users: use 2.0.




org.omnifaces
omnifaces
2.0



Handle f:viewParam validation fail with a redirect or error status



You've perhaps stumbled upon at least one of the following functional requirements:




  • Send a redirect when a has failed validation (e.g. absent, invalid format, unknown value, etc)

  • Send a HTTP error when a has failed validation (e.g. absent, invalid format, unknown value, etc)



Generally, the answer was to fiddle around in @PostConstruct, , or preRenderView and explicitly check for FacesContext#isPostback() and/or #isValidationFailed() and then deal with it using ExternalContext#redirect() or #sendError(). And then you've perhaps also take messaging into account and/or ignore the "Faces message has been enqueued but is not displayed" warnings over all place in logs.



OmniFaces now comes with a taghandler for this very purpose which can be applied per , or for them all. Here's an example which sends a HTTP 400 error when the foo parameter is absent.



 name="foo" required="true" >
sendError="400" />



Note that the is being used instead of to bypass a design mistake in . Namely, it works only exactly like as when an empty string is supplied as request parameter instead of null. So, when the request parameter is totally absent, i.e. it is null, then the behaves internally differently, causing among others postValidateEvent listeners and even JSR303 bean validation annotations such as @NotNull to be entirely skipped.




Stream images directly from backing bean, optionally as data URI



The is relatively limited in usage. In JSF 1.x it only generates a HTML element without any true JSF advantages. It didn't support e.g. directly referencing a byte[] or InputStream property representing the raw image content. You could just as well use plain HTML directly. In JSF 2.x, it got additional support for referencing JSF resources via new name and library attributes. However, it still didn't support directly referencing the image's content as bean property.



PrimeFaces came with which supported referencing a special wrapper class StreamedContent which in turn should contain among others the image via an InputStream. However, this caused much trouble and confusion among starters because the majority created and assigned it as a property of a request or view scoped bean during some postback bean action. This won't work because the webbrowser requests the image in a different and independent HTTP GET request, during which the initial request scoped bean won't exist anymore, and the JSF view state of the initial view (and thus also the view scoped bean) isn't available anywhere. Basically, you'd need to create the StreamedContent only in the getter method. This is fleshed out in the answer of among others the following questions:





Whilst the getter method approach worked, this ultimately ended up in ugly and confusing backing bean code, because the getter method is called twice and you only needed to populate the StreamedContent with the image's content in the second (stateless) call. You'd be tempted to just switch to a plain vanilla @WebServlet for the sole purpose of serving images, or to use the data URI scheme to immediately render the image content directly embedded in the HTML output.



OmniFaces now comes with a component which solves all of those problems. It supports directly referencing a byte[] or InputStream property representing the raw image content. It also immediately validates if the managed bean holding the property is @ApplicationScoped, so that the developer is automatically forced to "do things the right way" (i.e. don't accidentally deal with request/view scoped state by declaring the byte[] or InputStream as an instance variable). And, it supports a new dataURI="true" attribute which will immediately embed the image in the HTML output, and hereby thus supporting the image as property of a request or view scoped bean which is set during some postback bean action (hereby providing a perfect solution for a "preview uploaded image" case without polluting the data store).



Here's an example which shows images from a DB in a loop. Note that the getter method basically immediately invokes the service call and that it's also really only invoked when the browser actually requests the image, and thus not during rendering the HTML output. The application scoped bean is basically acting like an image servlet/service, but then with less boilerplate code than e.g. the @WebServlet approach.



@Named
@RequestScoped
public class Bean {

private List images; // Image class should NOT have "content" property, or at least it be lazy loaded.

@Inject
private ImageService service;

@PostConstruct
public void init() {
images = service.list();
}

public List getImages() {
return images;
}

}


@Named
@ApplicationScoped
public class ImageStreamer {

@Inject
private ImageService service;

public byte[] getById(Long id) {
return service.getContent(id);
}

}


 value="#{bean.images}" var="image">
value="#{imageStreamer.getById(image.id)}" />


See the showcase for live examples, with among others an upload-preview example.





Inject, convert and validate HTTP request parameters via CDI and have them ready in @PostConstruct



The @Param has been improved to support directly injecting the desired target type. So instead of



@Inject @Param private ParamValue paramName;


you can now finally use

@Inject @Param private String paramName;


, lowering the burden to actually use it. It even supports injecting (auto)converted values like so

@Inject @Param private Product product;


with a @FacesConverter(forClass=Product.class).



The major advantage as compared to is that the injected value is readily available in @PostConstruct and you don't need an additional (or the JSF 2.0/2.1 workaround) to perform the desired bean initialization based on those params. The disadvantage is that it's fully decoupled from the JSF lifecycle. I.e. conversion and validation is performed immediately during bean's construction, which is not necessarily during validations phase. Also, you would still need an additional Faces#isValidationFailed() check inside the @PostConstruct if you'd like to conditionally perform bean initialization depending on the validation outcome.



It doesn't make entirely superfluous, but depending on the business requirements it's a pretty good alternative as it makes the model (the backing bean) more declarative and the view (the XHTML) more clean. For example, one of the disadvantages of is that you can't declare it in a common template file and thus you'd have to copypaste it over all template clients. This can be solved by replacing it by using @Param on the common backing bean.



An overview of all additions/changes/bugfixes in OmniFaces 2.0



Taken over from the What's new? page on showcase:



Added in OmniFaces 2.0 (does NOT apply to 1.10)



  • NoAutoGeneratedIdViewHandler which throws a runtime exception when an autogenerated JSF client ID is being rendered

  • which enables sending either a redirect or error status on validation failure of view parameters

  • which is capable of referencing a byte[] or InputStream property with optional support for data URI format

  • @Param now supports directly injecting the (auto-converted) value

  • via which components, facets and behaviors can be moved at runtime to a target component in various ways

  • via which a component can be looked up by its ID and a reference to it put in various scopes

  • now supports validating beans at the class level

  • Servlets utility class got a bunch of new methods related to cookies and JSF

  • New BeansLocal utility class next to Beans class with the same philosophy as Faces/FacesLocal



Changed in OmniFaces 2.0 (also applies to 1.10)



  • Default validation message of ValidateMultipleFields components can now be supplied via

  • enables support for @NotNull and Pre/PostValidateEvent even when parameter is not specified, on contrary to

  • Html5RenderKit is now not forgiving anymore on broken renderers that don't pass the current component to the write methods (fixes "plain HTML" messup)

  • Skip null/empty values in as that's actually the responsibility of required="true"

  • CDNResourceHandler and CombinedResourceHandler can now be disabled via a web.xml context param supporting a request based EL expression



Fixed in OmniFaces 2.0 (also applies to 1.10)



  • Set system default timezone in CDI @FacesConverter when web.xml context param says so

  • Components#hasInvokedSubmit() failed in iterating components such as UIData and UIRepeat

  • Fixed to only consider own children instead of those of parent

  • GzipResponseFilter is made better compatible with Servlet 3.1 containers



Maven download stats


Here are the Maven download stats:



  • June 2014: 4429

  • July 2014: 4243

  • August 2014: 4169

  • September 2014: 4531

  • October 2014: 3651



Below is the version pie of October 2014:





But ... I don't want / can't use CDI at all!



Don't panic! OmniFaces 1.10 is the new release from the 1.x branch and is the same as 1.8.1, but with the bugfixes from 2.0 (but no additions!) and without any CDI dependency. This still depends on Java 1.6, JSF 2.0, EL 2.1 and Servlet 2.5 like the previous 1.x releases. The CDI part, which was optional since 1.6, has completely been removed (except for the org.omnifaces.config.BeanManager singleton enum, which uses reflection anyway). The reason for this is that some 1.x users were unable to upgrade to OmniFaces 1.6 or newer in an outdated environment due to bugs or conflicts in the ancient CDI library used.



I can't say if this will be the last OmniFaces 1.x release. If there's a bug report which applies to both 1.x and 2.x, then it will be fixed for both versions. The 1.x release won't contain any new features. This is not only to push users towards CDI, but also because any newer features will most likely also depend on the existence of new APIs. For example, the depends on JSF 2.1 and depends on EL 2.2.



Non-Maven users: download OmniFaces 1.10 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.



Maven users: use 1.10.




org.omnifaces
omnifaces
1.10


Vdldoc 2.0



Vdldoc, our Facelets .taglib.xml documentation generator, has also had its 2.0 release. The Java 7 javadoc look'n'feel has been upgraded to Java 8 javadoc look'n'feel. It now also supports Java EE 7's http://xmlns.jcp.org/* XML namespace. There are no other technical/functional changes.



Source:http://balusc.blogspot.com/2014/11/omnifaces-20-released.html

Tidak ada komentar:

Posting Komentar