jaxb unmarshall localDateTime multi thread environment - jaxb

In advance sorry for my bad english.
I have a problem when unmarshalling a string into a LocalDateTime in a multi thread environment. I generated the java classe (ActivityData) with org.apache.cxf version 2.7.7
When I debug the application from time to time the year of the string has been corrupted with some strange value at the beginning of the year (for instance 722008-01-01, A2008-01-01, 12008-01-01) when I make the call with a client like soap ui the date is well formatted. The localDateAdapter is called by multiple thread in a batch application. When I rerun the batch, the same call successes and others fails the parsing error is unpreddictable. The problem only occurs for the begin date the end date in the java object is always well formatted
I tried to synchronize the method but it doesn't change a thing.
Thanks in advance for your help
Here is the code of my LocalDateTimeAdapter
public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
public synchronized LocalDateTime unmarshal(String v) {
if (StringUtils.isNotBlank(v)) {
try {
return LocalDateTime.parse(v, DateTimeFormatter.ISO_DATE_TIME);
} catch (Exception exception) {
throw new IllegalArgumentException("Parsing problem in the localDateTime for string : " + v);
}
}
return null;
}
public String marshal(LocalDateTime v) {
if (v != null) {
return v.toString();
}
return StringUtils.EMPTY;
}
}
The generated class :
the binding file :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_1.xsd"
jaxb:extensionBindingPrefixes="xjc annox"
version="2.1">
<jaxb:globalBindings>
<jaxb:serializable uid="1"/>
<xjc:javaType
name="java.time.LocalDate"
xmlType="xs:date"
adapter="be.fgov.minfin.vies.adapter.LocalDateAdapter"/>
<xjc:javaType
name="java.time.LocalDateTime"
xmlType="xs:dateTime"
adapter="be.fgov.minfin.vies.adapter.LocalDateTimeAdapter"/>
</jaxb:globalBindings>
</jaxb:bindings>
the generated class :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ActivityData", propOrder = {
"beginDate",
"endDate"
})
public class ActivityData
implements Serializable
{
private final static long serialVersionUID = 1L;
#XmlElement(type = String.class)
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
#XmlSchemaType(name = "dateTime")
protected LocalDateTime beginDate;
#XmlElement(type = String.class)
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
#XmlSchemaType(name = "dateTime")
protected LocalDateTime endDate;
/**
* Gets the value of the beginDate property.
*
* #return
* possible object is
* {#link String }
*
*/
public LocalDateTime getBeginDate() {
return beginDate;
}
/**
* Sets the value of the beginDate property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setBeginDate(LocalDateTime value) {
this.beginDate = value;
}
/**
* Gets the value of the endDate property.
*
* #return
* possible object is
* {#link String }
*
*/
public LocalDateTime getEndDate() {
return endDate;
}
/**
* Sets the value of the endDate property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setEndDate(LocalDateTime value) {
this.endDate = value;
}
}

Related

parse json and get attributes with rest controller java

I have this code, the entity is persistable I want to make it non persistable so I parse json file and get name and icon values and display them instead of getting this values from database so that is why I want to change this code
/**
* A Pcomponent.
*/
#Entity
#Table(name = "pcomponent")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Pcomponent implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "icon")
private String icon;
#Column(name = "name")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getIcon() {
return icon;
}
public Pcomponent icon(String icon) {
this.icon = icon;
return this;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getName() {
return name;
}
public Pcomponent name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pcomponent pcomponent = (Pcomponent) o;
if (pcomponent.id == null || id == null) {
return false;
}
return Objects.equals(id, pcomponent.id);
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "Pcomponent{" +
"id=" + id +
", icon='" + icon + "'" +
", name='" + name + "'" +
'}';
}
}
/**
* Spring Data JPA repository for the Pcomponent entity.
*/
public interface PcomponentRepository extends
JpaRepository<Pcomponent,Long> {
}
/**
* A DTO for the Pcomponent entity.
*/
public class PcomponentDTO implements Serializable {
private Long id;
private String icon;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PcomponentDTO pcomponentDTO = (PcomponentDTO) o;
if ( ! Objects.equals(id, pcomponentDTO.id)) {
return false;
}
return true;
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "PcomponentDTO{" +
"id=" + id +
", icon='" + icon + "'" +
", name='" + name + "'" +
'}';
}
}
/**
* Mapper for the entity Pcomponent and its DTO PcomponentDTO.
*/
#Mapper(componentModel = "spring", uses = {})
public interface PcomponentMapper {
PcomponentDTO pcomponentToPcomponentDTO(Pcomponent pcomponent);
List<PcomponentDTO> pcomponentsToPcomponentDTOs(List<Pcomponent> pcomponents);
Pcomponent pcomponentDTOToPcomponent(PcomponentDTO pcomponentDTO);
List<Pcomponent> pcomponentDTOsToPcomponents(List<PcomponentDTO> pcomponentDTOs);
/**
* generating the fromId for all mappers if the databaseType is sql, as the class has relationship to it might need it, instead of
* creating a new attribute to know if the entity has any relationship from some other entity
*
* #param id id of the entity
* #return the entity instance
*/
default Pcomponent pcomponentFromId(Long id) {
if (id == null) {
return null;
}
Pcomponent pcomponent = new Pcomponent();
pcomponent.setId(id);
return pcomponent;
}
}
/**
* Service Implementation for managing Pcomponent.
*/
#Service
#Transactional
public class PcomponentService {
private final Logger log =
LoggerFactory.getLogger(PcomponentService.class);
private final PcomponentRepository pcomponentRepository;
private final PcomponentMapper pcomponentMapper;
public PcomponentService(PcomponentRepository pcomponentRepository, PcomponentMapper pcomponentMapper) {
this.pcomponentRepository = pcomponentRepository;
this.pcomponentMapper = pcomponentMapper;
}
/**
* Save a pcomponent.
*
* #param pcomponentDTO the entity to save
* #return the persisted entity
*/
public PcomponentDTO save(PcomponentDTO pcomponentDTO) {
log.debug("Request to save Pcomponent : {}", pcomponentDTO);
Pcomponent pcomponent = pcomponentMapper.pcomponentDTOToPcomponent(pcomponentDTO);
pcomponent = pcomponentRepository.save(pcomponent);
PcomponentDTO result = pcomponentMapper.pcomponentToPcomponentDTO(pcomponent);
return result;
}
/**
* Get all the pcomponents.
*
* #param pageable the pagination information
* #return the list of entities
*/
#Transactional(readOnly = true)
public Page<PcomponentDTO> findAll(Pageable pageable) {
log.debug("Request to get all Pcomponents");
Page<Pcomponent> result = pcomponentRepository.findAll(pageable);
return result.map(pcomponent -> pcomponentMapper.pcomponentToPcomponentDTO(pcomponent));
}
/**
* Get one pcomponent by id.
*
* #param id the id of the entity
* #return the entity
*/
#Transactional(readOnly = true)
public PcomponentDTO findOne(Long id) {
log.debug("Request to get Pcomponent : {}", id);
Pcomponent pcomponent = pcomponentRepository.findOne(id);
PcomponentDTO pcomponentDTO = pcomponentMapper.pcomponentToPcomponentDTO(pcomponent);
return pcomponentDTO;
}
/**
* Delete the pcomponent by id.
*
* #param id the id of the entity
*/
public void delete(Long id) {
log.debug("Request to delete Pcomponent : {}", id);
pcomponentRepository.delete(id);
}
}
/**
* REST controller for managing Pcomponent.
*/
#RestController
#RequestMapping("/api")
public class PcomponentResource {
private final Logger log =
LoggerFactory.getLogger(PcomponentResource.class);
private static final String ENTITY_NAME = "pcomponent";
private final PcomponentService pcomponentService;
public PcomponentResource(PcomponentService pcomponentService) {
this.pcomponentService = pcomponentService;
}
/**
* POST /pcomponents : Create a new pcomponent.
*
* #param pcomponentDTO the pcomponentDTO to create
* #return the ResponseEntity with status 201 (Created) and with body the new pcomponentDTO, or with status 400 (Bad Request) if the pcomponent has already an ID
* #throws URISyntaxException if the Location URI syntax is incorrect
*/
#PostMapping("/pcomponents")
#Timed
public ResponseEntity<PcomponentDTO> createPcomponent(#RequestBody PcomponentDTO pcomponentDTO) throws URISyntaxException {
log.debug("REST request to save Pcomponent : {}", pcomponentDTO);
if (pcomponentDTO.getId() != null) {
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new pcomponent cannot already have an ID")).body(null);
}
PcomponentDTO result = pcomponentService.save(pcomponentDTO);
return ResponseEntity.created(new URI("/api/pcomponents/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
/**
* PUT /pcomponents : Updates an existing pcomponent.
*
* #param pcomponentDTO the pcomponentDTO to update
* #return the ResponseEntity with status 200 (OK) and with body the updated pcomponentDTO,
* or with status 400 (Bad Request) if the pcomponentDTO is not valid,
* or with status 500 (Internal Server Error) if the pcomponentDTO couldnt be updated
* #throws URISyntaxException if the Location URI syntax is incorrect
*/
#PutMapping("/pcomponents")
#Timed
public ResponseEntity<PcomponentDTO> updatePcomponent(#RequestBody PcomponentDTO pcomponentDTO) throws URISyntaxException {
log.debug("REST request to update Pcomponent : {}", pcomponentDTO);
if (pcomponentDTO.getId() == null) {
return createPcomponent(pcomponentDTO);
}
PcomponentDTO result = pcomponentService.save(pcomponentDTO);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, pcomponentDTO.getId().toString()))
.body(result);
}
/**
* GET /pcomponents : get all the pcomponents.
*
* #param pageable the pagination information
* #return the ResponseEntity with status 200 (OK) and the list of pcomponents in body
*/
#GetMapping("/pcomponents")
#Timed
public ResponseEntity<List<PcomponentDTO>> getAllPcomponents(#ApiParam Pageable pageable) {
log.debug("REST request to get a page of Pcomponents");
Page<PcomponentDTO> page = pcomponentService.findAll(pageable);
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/pcomponents");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
/**
* GET /pcomponents/:id : get the "id" pcomponent.
*
* #param id the id of the pcomponentDTO to retrieve
* #return the ResponseEntity with status 200 (OK) and with body the pcomponentDTO, or with status 404 (Not Found)
*/
#GetMapping("/pcomponents/{id}")
#Timed
public ResponseEntity<PcomponentDTO> getPcomponent(#PathVariable Long id) {
log.debug("REST request to get Pcomponent : {}", id);
PcomponentDTO pcomponentDTO = pcomponentService.findOne(id);
return ResponseUtil.wrapOrNotFound(Optional.ofNullable(pcomponentDTO));
}
/**
* DELETE /pcomponents/:id : delete the "id" pcomponent.
*
* #param id the id of the pcomponentDTO to delete
* #return the ResponseEntity with status 200 (OK)
*/
#DeleteMapping("/pcomponents/{id}")
#Timed
public ResponseEntity<Void> deletePcomponent(#PathVariable Long id) {
log.debug("REST request to delete Pcomponent : {}", id);
pcomponentService.delete(id);
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
}
}

JSF h:selectonemenu convertor Validation error value is not valid [duplicate]

This question already has answers here:
Validation Error: Value is not valid
(3 answers)
Closed 7 years ago.
I know this has been discussed a lot, and I also tried most of resolution, but I still got this error:
sourceId=comboNewTaskParent[severity=(ERROR 2), summary=(comboNewTaskParent: Validation Error: Value is not valid), detail=(comboNewTaskParent: Validation Error: Value is not valid)]
Here is the code for HTML:
<h:outputLabel value="Parent task" for="comboNewTaskParent" />
<div class="formRight">
<h:selectOneMenu id="comboNewTaskParent" value="#{taskController.parentTask}" converter="#{taskConverter}"
<f:selectItems value="#{comboTaskByProject}" var="task" itemValue="#{task}" itemLabel="#{task.taskName}" />
</h:selectOneMenu>
</div>
Here is the code of my entity bean:
package com.projectportal.entity;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
/**
* The persistent class for the Task database table.
*
*/
#Entity
#Table(name="Task")
public class Task implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(unique=true, nullable=false, length=36)
private String taskId;
#Column(length=1000)
private String taskDesc;
#Column(nullable=false)
private int taskDurationHour;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable=false)
private Date taskEstimated;
#Column(nullable=false, length=200)
private String taskName;
#Column(nullable=false)
private float taskPercentComplete;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable=false)
private Date taskStartDate;
//bi-directional many-to-one association to Priority
#ManyToOne
#JoinColumn(name="priorityId", nullable=false)
private Priority priority;
//bi-directional many-to-one association to Project
#ManyToOne
#JoinColumn(name="projectId")
private Project project;
//bi-directional many-to-one association to Status
#ManyToOne
#JoinColumn(name="statusId", nullable=false)
private Status status;
//bi-directional many-to-one association to Task
#ManyToOne
#JoinColumn(name="parentTaskId")
private Task parentTask;
//bi-directional many-to-one association to Task
#OneToMany(mappedBy="parentTask")
private List<Task> childTasks;
//bi-directional many-to-one association to Task
#ManyToOne
#JoinColumn(name="preTaskId")
private Task preTask;
//bi-directional many-to-one association to Task
#OneToMany(mappedBy="preTask")
private List<Task> dependentTasks;
//bi-directional many-to-one association to UserXTask
#OneToMany(mappedBy="task")
private List<UserXTask> userXtasks;
public Task() {
}
public String getTaskId() {
return this.taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getTaskDesc() {
return this.taskDesc;
}
public void setTaskDesc(String taskDesc) {
this.taskDesc = taskDesc;
}
public int getTaskDurationHour() {
return this.taskDurationHour;
}
public void setTaskDurationHour(int taskDurationHour) {
this.taskDurationHour = taskDurationHour;
}
public Date getTaskEstimated() {
return this.taskEstimated;
}
public void setTaskEstimated(Date taskEstimated) {
this.taskEstimated = taskEstimated;
}
public String getTaskName() {
return this.taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public float getTaskPercentComplete() {
return this.taskPercentComplete;
}
public void setTaskPercentComplete(float taskPercentComplete) {
this.taskPercentComplete = taskPercentComplete;
}
public Date getTaskStartDate() {
return this.taskStartDate;
}
public void setTaskStartDate(Date taskStartDate) {
this.taskStartDate = taskStartDate;
}
public Priority getPriority() {
return this.priority;
}
public void setPriority(Priority priority) {
this.priority = priority;
}
public Project getProject() {
return this.project;
}
public void setProject(Project project) {
this.project = project;
}
public Status getStatus() {
return this.status;
}
public void setStatus(Status status) {
this.status = status;
}
public Task getParentTask() {
return this.parentTask;
}
public void setParentTask(Task parentTask) {
this.parentTask = parentTask;
}
public List<Task> getChildTasks() {
return this.childTasks;
}
public void setChildTasks(List<Task> childTasks) {
this.childTasks = childTasks;
}
public Task getPreTask() {
return this.preTask;
}
public void setPreTask(Task preTask) {
this.preTask = preTask;
}
public List<Task> getDependentTasks() {
return this.dependentTasks;
}
public void setDependentTasks(List<Task> dependentTasks) {
this.dependentTasks = dependentTasks;
}
public List<UserXTask> getUserXtasks() {
return this.userXtasks;
}
public void setUserXtasks(List<UserXTask> userXtasks) {
this.userXtasks = userXtasks;
}
}
The controller:
public #Model class TaskController {
#Inject private EntityManager em;
#Inject Identity identity;
#Inject Logger log;
#Inject Event<Task> taskEventSrc;
#Named
#Produces
private List<Task> requestTaskList;
private Task parentTask;
private Task newTask;
#Produces
#Named
public Task getNewTask(){
return this.newTask;
}
/**
*
*/
public TaskController() {
// TODO Auto-generated constructor stub
}
#PostConstruct
public void loadSelfTasks(){
// Init
newTask = new Task();
// Get user from DB.
User user = em.find(User.class, identity.getUser().getId());
requestTaskList = new ArrayList<Task>();
// Loop user's tasks.
for(UserXTask userTask : user.getUserXtasks()){
requestTaskList.add(userTask.getTask());
}
log.info("Tasks for user: " + user.getFirstname() + " loaded.");
}
/**
* Create task.
* #throws Exception
*/
public void createTask() throws Exception{
log.info("Persistencing task: " + newTask.getParentTask().getTaskId());
em.persist(newTask);
taskEventSrc.fire(newTask);
newTask = new Task();
}
/**
* #return the parentTask
*/
public Task getParentTask() {
return parentTask;
}
/**
* #param parentTask the parentTask to set
*/
public void setParentTask(Task parentTask) {
this.parentTask = parentTask;
}
}
And of course the converter:
#Named
/**
* #author lastcow
*
*/
public class TaskConverter implements Converter {
#Inject EntityManager em;
#Inject Logger log;
/* (non-Javadoc)
* #see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
*/
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
log.info("=========== Convert to Object " + value);
if(value.equals("0")){
return null;
}
Task t = em.find(Task.class, value);
log.info("======== Got : " + t.getTaskName());
return t;
}
/* (non-Javadoc)
* #see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
*/
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
log.info("=========== Convert to String " + value);
return ((Task)value).getTaskId();
}
}
from what logged, the convert are working as it, but when I try to submit the form, always throw 'Validation Error: Value is not valid' ERROR, I have struck here for almost 2 days.
Anyone please give some suggestions.
BTW, I tried put equals and hashCode in Task.java, doesn't working either.
Thanks in advance.
Validation Error: Value is not valid
This error will be thrown when the equals() method of the selected item hasn't returned true for any of the available items in <f:selectItem(s)>. Thus, this can technically have only 2 causes:
The equals() method of your Task class is missing or broken.
The <f:selectItems value="#{comboTaskByProject}"> has incompatibly changed during the postback request of the form submit as compared to during the initial request of the form display.
To fix cause #1, make sure that you understand how to implement equals() properly. You can find kickoff examples here: Right way to implement equals contract
To fix cause #2, make sure that the #{comboTaskByProject} never canges during postback. Best is to put it in the view scope or broader, or to make sure that request based conditions for populating that list are preserved in the postback request by e.g. using <f:viewParam>.
See also:
Our selectOneMenu wiki page
Validation Error: Value is not valid
I am not sure which version of JSF you are using. As far as I know, the converter in HTML should be used like this converter="javax.faces.DateTime". Where this part javax.faces.DateTime is converter name defined in faces-config.xml or in converter class with #FacesConverter.

Read resource bundle properties in a managed bean

Using <resource-bundle> files I'm able to have i18n text in my JSF pages.
But is it possible to access these same properties in my managed bean so I can set faces messages with i18n values?
Assuming that you've configured it as follows:
<resource-bundle>
<base-name>com.example.i18n.text</base-name>
<var>text</var>
</resource-bundle>
If your bean is request scoped, you can just inject the <resource-bundle> as #ManagedProperty by its <var>:
#ManagedProperty("#{text}")
private ResourceBundle text;
public void someAction() {
String someKey = text.getString("some.key");
// ...
}
Or if you just need some specific key:
#ManagedProperty("#{text['some.key']}")
private String someKey;
public void someAction() {
// ...
}
If your bean is however in a broader scope, then evaluate #{text} programmatically in method local scope:
public void someAction() {
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle text = context.getApplication().evaluateExpressionGet(context, "#{text}", ResourceBundle.class);
String someKey = text.getString("some.key");
// ...
}
Or if you only need some specific key:
public void someAction() {
FacesContext context = FacesContext.getCurrentInstance();
String someKey = context.getApplication().evaluateExpressionGet(context, "#{text['some.key']}", String.class);
// ...
}
You can even just get it by the standard ResourceBundle API the same way as JSF itself is already doing under the covers, you'd only need to repeat the base name in code:
public void someAction() {
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle text = ResourceBundle.getBundle("com.example.i18n.text", context.getViewRoot().getLocale());
String someKey = text.getString("some.key");
// ...
}
Or if you're managing beans by CDI instead of JSF, then you can create a #Producer for that:
public class BundleProducer {
#Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{text}", PropertyResourceBundle.class);
}
}
And inject it as below:
#Inject
private PropertyResourceBundle text;
Alternatively, if you're using the Messages class of the JSF utility library OmniFaces, then you can just set its resolver once to let all Message methods utilize the bundle.
Messages.setResolver(new Messages.Resolver() {
public String getMessage(String message, Object... params) {
ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.text", Faces.getLocale());
if (bundle.containsKey(message)) {
message = bundle.getString(message);
}
return MessageFormat.format(message, params);
}
});
See also the example in the javadoc and the showcase page.
Another possibility:
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config ...>
<application>
<locale-config>
<default-locale>de</default-locale>
</locale-config>
<resource-bundle>
<base-name>de.fhb.resources.text.backend</base-name>
<var>backendText</var>
</resource-bundle>
</application>
</faces-config>
YourBean.java
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle backendText = app.getResourceBundle(context, "backendText");
backendText.getString("your.property.key");
Here is a solution I'm using, not as simple but at least working :
First class :
package com.spectotechnologies.website.util;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
/**
*
* #author Alexandre Lavoie
*/
public class MessageInterpolator extends ResourceBundleMessageInterpolator
{
public static final String LANGUAGE_TAG_PATTERN = "\\{[^}]*\\}";
#Override
public String interpolate(String p_sMessage, Context p_oContext)
{
return super.interpolate(replaceMessages(p_sMessage),p_oContext);
}
#Override
public String interpolate(String p_sMessage, Context p_oContext, Locale p_oLocale)
{
StringManager.setLocale(p_oLocale);
return super.interpolate(replaceMessages(p_sMessage),p_oContext,p_oLocale);
}
private String replaceMessages(String p_sMessage)
{
Matcher oMatcher;
String sKey;
String sReplacement;
StringBuffer sbTemp = new StringBuffer();
oMatcher = Pattern.compile(LANGUAGE_TAG_PATTERN).matcher(p_sMessage);
while(oMatcher.find())
{
sKey = oMatcher.group().substring(1,oMatcher.group().length() - 1);
sReplacement = StringManager.getString(sKey);
if(!sReplacement.startsWith("???"))
{
oMatcher.appendReplacement(sbTemp,sReplacement);
}
}
oMatcher.appendTail(sbTemp);
return sbTemp.toString();
}
}
Second class :
package com.spectotechnologies.website.util;
import com.spectotechnologies.util.BundleManager;
import com.spectotechnologies.util.FacesSessionManager;
import java.util.Locale;
/**
* set-up and interface a BundleManager
* save the bundleManager into the session
* #author Charles Montigny
*/
public final class StringManager
{
/** the session name of this class bundle manager */
public static final String BUNDLE_MANAGER_SESSION_NAME = "StringManager_BundleManager";
/** List of ResourceBundle names to load.
* Will be load in order.
* The last ones values may overrite the first ones values. */
private final static String[] BUNDLE_LIST = {
"com.spectotechnologies.hibernate.validation.resources.ValidationMessages",
"com.spectotechnologies.website.general.resources.ValidationMessages",
"com.spectotechnologies.website.general.resources.General"};
/** bundle manager */
private static BundleManager m_oBundleManager = null;
private static BundleManager getBundleManager()
{
if(m_oBundleManager == null)
{
// get the bundle into the session
m_oBundleManager = (BundleManager)FacesSessionManager.getObject(BUNDLE_MANAGER_SESSION_NAME);
if(m_oBundleManager == null)
{
// session was empty, load a new one
m_oBundleManager = new BundleManager();
for(int iIndex = 0; iIndex < BUNDLE_LIST.length; iIndex++)
{
m_oBundleManager.addBundle(BUNDLE_LIST[iIndex]);
}
// add the bundle to the session
FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME, m_oBundleManager);
}
}
return m_oBundleManager;
}
/**
* get a string value in the bundle manager by a string key
* #param p_sKey the string key
* #return the value of the string key
*/
public static String getString(String p_sKey)
{
return getBundleManager().getStringValue(p_sKey);
}
/**
* set the locale
* #param p_oLocale the locale to set
*/
public static void setLocale(Locale p_oLocale)
{
getBundleManager().setLocale(p_oLocale);
// update the session
FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME,
getBundleManager());
}
}
After you need to override BUNDLE_LIST with your properties files. Once done, use it like that :
sMessage = StringManager.getString("website.validation.modifySystem.modified");
If you have questions, do not hesitate!
EDIT :
You also need to declare the MessageInterpolator
META-INF/validation.xml
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">
<message-interpolator>com.spectotechnologies.website.util.MessageInterpolator</message-interpolator>
</validation-config>

JSF2.0 simple file input

I'm trying to add a very simple file input to my webapp which I'm doing using JSF2.0 and RichFaces 3.3.3, the thing is I really dislike the richfaces fileInput component and I'm looking for something simpler (in terms of use and looks), so far I've found:
tomahawk's fileInput - but tomahawk only supports JSF1.2
trinidad fileInput - but trinidad for JSF2.0 is in alpha stage
primefaces - but of course they won't work with RichFaces 3.3.3 (only 4.0 which are in beta)
Are there any other options? I need something really simple like a normal html file input component.
You basically need to do two things:
Create a Filter which puts the multipart/form-data items in a custom map and replace the original request parameter map with it so that the normal request.getParameter() process keeps working.
Create a JSF 2.0 custom component which renders a input type="file" and which is aware of this custom map and can obtain the uploaded files from it.
#taher has already given a link where you could find insights and code snippets. The JSF 2.0 snippets should be reuseable. You yet have to modify the MultipartMap to use the good 'ol Apache Commons FileUpload API instead of the Servlet 3.0 API.
If I have time, I will by end of day rewrite it and post it here.
Update: I almost forgot you, I did a quick update to replace Servlet 3.0 API by Commons FileUpload API, it should work:
package net.balusc.http.multipart;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
public class MultipartMap extends HashMap<String, Object> {
// Constants ----------------------------------------------------------------------------------
private static final String ATTRIBUTE_NAME = "parts";
private static final String DEFAULT_ENCODING = "UTF-8";
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
// Vars ---------------------------------------------------------------------------------------
private String encoding;
private String location;
// Constructors -------------------------------------------------------------------------------
/**
* Construct multipart map based on the given multipart request and file upload location. When
* the encoding is not specified in the given request, then it will default to <tt>UTF-8</tt>.
* #param multipartRequest The multipart request to construct the multipart map for.
* #param location The location to save uploaded files in.
* #throws ServletException If something fails at Servlet level.
* #throws IOException If something fails at I/O level.
*/
#SuppressWarnings("unchecked") // ServletFileUpload#parseRequest() isn't parameterized.
public MultipartMap(HttpServletRequest multipartRequest, String location)
throws ServletException, IOException
{
multipartRequest.setAttribute(ATTRIBUTE_NAME, this);
this.encoding = multipartRequest.getCharacterEncoding();
if (this.encoding == null) {
multipartRequest.setCharacterEncoding(this.encoding = DEFAULT_ENCODING);
}
this.location = location;
try {
List<FileItem> parts = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(multipartRequest);
for (FileItem part : parts) {
if (part.isFormField()) {
processFormField(part);
} else if (!part.getName().isEmpty()) {
processFileField(part);
}
}
} catch (FileUploadException e) {
throw new ServletException("Parsing multipart/form-data request failed.", e);
}
}
// Actions ------------------------------------------------------------------------------------
#Override
public Object get(Object key) {
Object value = super.get(key);
if (value instanceof String[]) {
String[] values = (String[]) value;
return values.length == 1 ? values[0] : Arrays.asList(values);
} else {
return value; // Can be File or null.
}
}
/**
* #see ServletRequest#getParameter(String)
* #throws IllegalArgumentException If this field is actually a File field.
*/
public String getParameter(String name) {
Object value = super.get(name);
if (value instanceof File) {
throw new IllegalArgumentException("This is a File field. Use #getFile() instead.");
}
String[] values = (String[]) value;
return values != null ? values[0] : null;
}
/**
* #see ServletRequest#getParameterValues(String)
* #throws IllegalArgumentException If this field is actually a File field.
*/
public String[] getParameterValues(String name) {
Object value = super.get(name);
if (value instanceof File) {
throw new IllegalArgumentException("This is a File field. Use #getFile() instead.");
}
return (String[]) value;
}
/**
* #see ServletRequest#getParameterNames()
*/
public Enumeration<String> getParameterNames() {
return Collections.enumeration(keySet());
}
/**
* #see ServletRequest#getParameterMap()
*/
public Map<String, String[]> getParameterMap() {
Map<String, String[]> map = new HashMap<String, String[]>();
for (Entry<String, Object> entry : entrySet()) {
Object value = entry.getValue();
if (value instanceof String[]) {
map.put(entry.getKey(), (String[]) value);
} else {
map.put(entry.getKey(), new String[] { ((File) value).getName() });
}
}
return map;
}
/**
* Returns uploaded file associated with given request parameter name.
* #param name Request parameter name to return the associated uploaded file for.
* #return Uploaded file associated with given request parameter name.
* #throws IllegalArgumentException If this field is actually a Text field.
*/
public File getFile(String name) {
Object value = super.get(name);
if (value instanceof String[]) {
throw new IllegalArgumentException("This is a Text field. Use #getParameter() instead.");
}
return (File) value;
}
// Helpers ------------------------------------------------------------------------------------
/**
* Process given part as Text part.
*/
private void processFormField(FileItem part) {
String name = part.getFieldName();
String[] values = (String[]) super.get(name);
if (values == null) {
// Not in parameter map yet, so add as new value.
put(name, new String[] { part.getString() });
} else {
// Multiple field values, so add new value to existing array.
int length = values.length;
String[] newValues = new String[length + 1];
System.arraycopy(values, 0, newValues, 0, length);
newValues[length] = part.getString();
put(name, newValues);
}
}
/**
* Process given part as File part which is to be saved in temp dir with the given filename.
*/
private void processFileField(FileItem part) throws IOException {
// Get filename prefix (actual name) and suffix (extension).
String filename = FilenameUtils.getName(part.getName());
String prefix = filename;
String suffix = "";
if (filename.contains(".")) {
prefix = filename.substring(0, filename.lastIndexOf('.'));
suffix = filename.substring(filename.lastIndexOf('.'));
}
// Write uploaded file.
File file = File.createTempFile(prefix + "_", suffix, new File(location));
InputStream input = null;
OutputStream output = null;
try {
input = new BufferedInputStream(part.getInputStream(), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(new FileOutputStream(file), DEFAULT_BUFFER_SIZE);
IOUtils.copy(input, output);
} finally {
IOUtils.closeQuietly(output);
IOUtils.closeQuietly(input);
}
put(part.getFieldName(), file);
part.delete(); // Cleanup temporary storage.
}
}
You still need both the MultipartFilter and MultipartRequest classes as described in this article. You only need to remove the #WebFilter annotation and map the filter on an url-pattern of /* along with an <init-param> of location wherein you specify the absolute path where the uploaded files are to be stored. You can use the JSF 2.0 custom file upload component as described in this article unchanged.
Dear either you have to use rich:uploadFile or make custom component in JSF by following http://balusc.blogspot.com/2009/12/uploading-files-with-jsf-20-and-servlet.html
After I also tried tomahawk, I mentioned that it does not work with AJAX. So I decided to hack rich:fileUpload and perform the click on add button over a a4j:commandButton. Here's the code:
<a4j:form id="myForm">
<a4j:commandButton id="myButton" value="Upload" title="Upload" styleClass="myButtonClass"
onclick="document.getElementById('myForm:myFileUpload:file').click()/>
<rich:fileUpload id="myFileUpload" maxFilesQuantity="1" autoclear="true"
immediateUpload="true" styleClass="invisibleClass"
fileUploadListener="#{uploadBean.uploadListener}"/>
</a4j:form>
myForm:myFileUpload:file is the input-Element (type="file") for the Add-Button. invisibleClass should only contain display:none;. With style="display:none;" it won't work.
You can used rich faces 3.3.3 file upload.
Step 1 : fileUpload.xhtml
<rich:fileUpload id="fileupload" addControlLabel="Browse"
required="true"
fileUploadListener="#{testForm.listener}"
acceptedTypes="xml"
ontyperejected="alert('Only xml files are accepted');"
maxFilesQuantity="1" listHeight="57px" listWidth="100%"
disabled="#{testForm..disabled}" >
<a4j:support event="onclear"
action="#{testForm..clearUploadData}"
reRender="fileupload" />
</rich:fileUpload>
Step 2: FileUpload.java
public class FileUpload implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String Name;
private String mime;
private long length;
private byte [] file;
private String absolutePath;
public String getName() {
return Name;
}
/**
* #return the file
*/
public byte[] getFile() {
return file;
}
/**
* #param file the file to set
*/
public void setFile(byte[] file) {
this.file = file;
}
/**
* #param mime the mime to set
*/
public void setMime(String mime) {
this.mime = mime;
}
public void setName(String name) {
Name = name;
int extDot = name.lastIndexOf('.');
if(extDot > 0){
String extension = name.substring(extDot +1);
if("txt".equals(extension)){
mime="txt";
} else if("xml".equals(extension)){
mime="xml";
} else {
mime = "unknown file";
}
}
}
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public String getMime(){
return mime;
}
/**
* #return the absolutePath
*/
public String getAbsolutePath() {
return absolutePath;
}
/**
* #param absolutePath the absolutePath to set
*/
public void setAbsolutePath(String absolutePath) {
this.absolutePath = absolutePath;
}
}
Step 3 :TestForm // calling listner
/**
*
* #param event
* #throws Exception
*/
public void listener(UploadEvent event) throws Exception{
UploadItem item = event.getUploadItem();
FileUpload file = new FileUpload();
file.setLength(item.getData().length);
file.setFile(item.getData());
file.setName(item.getFileName());
files.add(file);
}

JSF Custom Image Component Problem to display multiple Image

Created a Tag Library Descriptor File:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>image</short-name>
<uri>/WEB-INF/tlds/image</uri>
<tag>
<name>BsilImage</name>
<tag-class>com.custom.image.ImageTagHandler</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>url</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>style</name>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>type</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
</taglib>
ImageTagHandler
public class ImageTagHandler extends UIComponentELTag {
private String url;
private String style;
private String type;
private static final String IMAGE_COMP_TYPE = "IMAGE_COMPONENT";
private static final String IMAGE_RENDERER_TYPE = "IMAGE_RENDERER";
public void setUrl(String url) {
this.url = url;
}
public void setStyle(String style) {
this.style = style;
}
public void setType(String type) {
this.type = type;
}
public String getComponentType() {
return IMAGE_COMP_TYPE;
}
public String getRendererType() {
return IMAGE_RENDERER_TYPE;
}
#Override
protected void setProperties(UIComponent component) {
super.setProperties(component);
ImageComponent imgComponent =
((ImageComponent) component);
if (type != null) {
imgComponent.setType(ImageTranscoder.getImageTypeOf(type));
}
if (url != null) {
imgComponent.setUrl(ImageTranscoder.getImagePath(url));
}
if (style != null) {
imgComponent.setStyle(style);
}
}
}
ImageComponent
public class ImageComponent extends UIOutput {
private String url;
private String style;
private String type;
private static final String IMAGE_COMP_FAMILY = "IMAGE_FAMILY";
#Override
public String getFamily() {
return IMAGE_COMP_FAMILY;
}
/**
* Get the value of type
*
* #return the value of type
*/
public String getType() {
return type;
}
/**
* Set the value of type
*
* #param type new value of type
*/
public void setType(String type) {
this.type = type;
}
/**
* Get the value of style
*
* #return the value of style
*/
public String getStyle() {
return style;
}
/**
* Set the value of style
*
* #param style new value of style
*/
public void setStyle(String style) {
this.style = style;
}
/**
* Get the value of url
*
* #return the value of url
*/
public String getUrl() {
return url;
}
/**
* Set the value of url
*
* #param url new value of url
*/
public void setUrl(String url) {
this.url = url;
}
}
ImageRenderer
public class ImageRenderer extends Renderer {
#Override
public void encodeBegin(FacesContext context, UIComponent component)
throws IOException {
ImageComponent imgComponent = (ImageComponent)component;
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div",component);
writer.startElement("img", imgComponent);
writer.writeAttribute("src",imgComponent.getUrl(), "url");
writer.writeAttribute("class", imgComponent.getStyle(), "style");
writer.endElement("div");
}
}
CODE TO ACCESS TAG LIB IS
<h:dataTable var="landing" binding="${LandingBean.tourPackages}" >
<h:column>
<tr:panelGroupLayout layout="vertical" styleClass="landingListing">
<bsil:BsilImage style="listingImage" url="${landing.photoThumbnail}" type="banner"/>
</tr:panelGroupLayout>
</h:column>
</h:dataTable>
The bean contain multiple photos which has to be shown in number of column when the page is displayed. The problem which I am facing is its cant show me multiple images gives an error saying
According to TLD or attribute
directive in tag file, attribute
binding does not accept any
expressions
If the bean contain single Image It is displayed the code for that is
<tr:panelHeader id="panelHeader" styleClass="banner" text="">
<bsil:BsilImage url="${LandingBean.bannerImage}"
style="bannerImage" type="banner"></bsil:BsilImage>
</tr:panelHeader>
I want to know how to display multiple images using custom component.
According to the error message you quoted, it seems that the issue is in the <h:dataTable ...> tag, it seems that its attribute called "binding" apparently doesn't accept expressions for some reason.
E.g.
<tag>
<name>dataTable</name>
<attribute>
<name>binding</name>
<!-- add this: -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
If you own the code of the dataTable tag, add <rtexprvalue>true</rtexprvalue> next to the "binding" attribute of that tag (like you did in your image tag). If you don't, refer to it's documentation and find out why it doesn't allow expressions.

Resources