PrimeFaces primeDateRangeValidator - Get variable - jsf

I need help with a problem i have using the primeDateRangeValidator.I need to get a variable (private boolean validacionFechas;) from this class and use it in another one. (Sorry for my bad english).
#FacesValidator("primeDateRangeValidator")
public class PrimeDateRangeValidator implements Validator {
private boolean validacionFechas;
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (value == null) {
return;
}
//Leave the null handling of startDate to required="true"
Object startDateValue = component.getAttributes().get("fi");
if (startDateValue==null) {
return;
}
Date startDate = (Date)startDateValue;
Date endDate = (Date)value;
if (endDate.before(startDate)) {
this.validacionFechas = false;
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "¡Error!", "La fecha inicial no puede ser mayor a la final."));
}
}
public boolean getValidacionFechas() {
return validacionFechas;
}
public void setValidacionFechas(boolean validacionFechas) {
this.validacionFechas = validacionFechas;
}
}
The validation between the dates are correct, and the message too. But from another class(where i have my Save method) i'm calling the variable this way:
PrimeDateRangeValidator pdrv = new PrimeDateRangeValidator();
pdrv.getValidacionFechas();
And i'm always getting TRUE, cousing this to save the information if the dates are correct, and when the dates are incorrect show the error message but saves the information too.
Is there any problem with the #FacesValidator or with the set and get?

Your implementation can't work. You are creating a new instance of PrimeDateRangeValidator which has nothing to do with the
validator instance that JSF creates and uses itself. I'm just wondering why getValidacionFechas always returns true. It should
return false.
I think the best way is to put the information of the validation into the session map, for example:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("VALIDACION_FECHAS", false);
And read it like that:
boolean validacionFechas = (boolean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("VALIDACION_FECHAS");

Related

Jooq- Updating a field to NULL makes it "null" and not NULL

So this was my query that previously worked in jooq 3.11.
I am updating a JSON field, however it is mapped to a String in my model using a JsonBinding which I will post down below
dsl.update(TASK)
.set(TASK.JSON_SOLUTION, (String) null).
.where(TASK.TENANT.eq(getCurrentTenant()))
.and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()
This now no longer works after upgrading to jooq 3.13.2. I also had to change my sql dialect to be mysql even though I am working with a mysql 5_7 database, this may be the issue?
I have also tried this and it is still the same
dsl.update(TASK)
.setNull(TASK.JSON_SOLUTION).
.where(TASK.TENANT.eq(getCurrentTenant()))
.and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()
JsonBinding.class
public class JsonBinding implements Binding<JSON, String> {
#Override
public Converter<JSON, String> converter() {
return new JsonConverter();
}
#Override
public void sql(BindingSQLContext<String> bindingSQLContext) {
if (bindingSQLContext.render().paramType() == ParamType.INLINED) {
bindingSQLContext
.render()
.visit(DSL.inline(bindingSQLContext.convert(converter()).value()))
.sql("::json");
} else {
bindingSQLContext.render().sql("?");
}
}
#Override
public void register(BindingRegisterContext<String> bindingRegisterContext) throws SQLException {
bindingRegisterContext
.statement()
.registerOutParameter(bindingRegisterContext.index(), Types.VARCHAR);
}
#Override
public void set(BindingSetStatementContext<String> bindingSetStatementContext)
throws SQLException {
bindingSetStatementContext
.statement()
.setString(
bindingSetStatementContext.index(),
Objects.toString(bindingSetStatementContext.convert(converter()).value(), null));
}
#Override
public void set(BindingSetSQLOutputContext<String> bindingSetSQLOutputContext)
throws SQLException {
throw new SQLFeatureNotSupportedException();
}
#Override
public void get(BindingGetResultSetContext<String> bindingGetResultSetContext)
throws SQLException {
bindingGetResultSetContext
.convert(converter())
.value(
JSON.valueOf(
bindingGetResultSetContext
.resultSet()
.getString(bindingGetResultSetContext.index())));
}
#Override
public void get(BindingGetStatementContext<String> bindingGetStatementContext)
throws SQLException {
bindingGetStatementContext
.convert(converter())
.value(
JSON.valueOf(
bindingGetStatementContext
.statement()
.getString(bindingGetStatementContext.index())));
}
#Override
public void get(BindingGetSQLInputContext<String> bindingGetSQLInputContext) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
}
JsonConverter.class
public class JsonConverter implements Converter<JSON, String> {
#Override
public String from(JSON object) {
return object != null ? object.toString() : null;
}
#Override
public JSON to(String string) {
return JSON.valueOf(string);
}
#Override
public Class<JSON> fromType() {
return JSON.class;
}
#Override
public Class<String> toType() {
return String.class;
}
}
Here is the query jooq runs with .setNull()
update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = 'null'::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))
Before the upgrade on jooq 3.11 the query comes out as this
update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = null::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))
So before its set 'json_solution' = null and after the upgrade it seems to be set 'json_solution' = 'null'
Not quite sure why this is occurring?
Edit: So from what I can tell this solely seems to be from the upgrade in JOOQ and not the sql-dialect. Using Jooq 3.11.5 with both mysql and mysql_5_7 as the dialects, the query is built as set 'json_solution' = null, if I upgrade JOOQ to 3.13.2 its set 'json_solution' = 'null'
This quirk also seems to only happen on the JSON field, I tried setting another varchar String field to be null on the same table, and I get the correct set "field_name' = null
The problem may be with my JsonBinding/JsonConverter ? I had to modify it slightly to work with the new JSON object in JOOQ, as previously JOOQ mapped JSON as Object
JSON.valueOf(null) vs (JSON) null
The answer is in the Javadoc of org.jooq.JSON:
A CAST(NULL AS JSON) value is represented by a null reference of type JSON, not as data() == null. This is consistent with jOOQ's general way of returning NULL from Result and Record methods.
So, the mistake is in JsonConverter's usage of JSON.valueOf(). Write this instead:
public JSON to(String string) {
return string == null ? null : JSON.valueOf(string);
}
Or, just use Converter.ofNullable(), which handles the null-to-null mapping for you:
Converter<JSON, String> converter = Converter.ofNullable(
JSON.class,
String.class,
JSON::data,
JSON::json
);
Side note on using a Binding
You don't really need the binding anymore, now that the JSON type is suppported natively by jOOQ. If you want to convert JSON to String, your Converter will be sufficient.

How to add condition based action to command button in ADF?

How to navigate to the next page based on the return value from the method called inside the action attribute of the command button.
<af:button id="tt_b2"
rendered="#{attrs.nextRendered}"
partialSubmit="true"
action="#{attrs.backingBean.nextAction}"
text="Next"
disabled="#{attrs.nextDisabled}"/>
private static final String NEXT_NAVIGATION_ACTION = "controllerContext.currentViewPort.taskFlowContext.trainModel.getNext";
public String nextAction() {
if (validate()) {
updateModel();
return NEXT_NAVIGATION_ACTION;
}
return null;
}
The use case is done for train model, which is implemented based on this blog : http://javacollectibles.blogspot.co.uk/2014/10/adf-train-template.html
We need to define a generic next action in the template but the action should be called conditionally, based on whether all the validation checks has been passed on not.
Try using ADFUtils.invokeEl
public String nextAction() {
if (validate()) {
updateModel();
return (String)ADFUtils.invokeEL(NEXT_NAVIGATION_ACTION);
}
return null;
}
Its ain't necessary to hardcode any steps, you can query TaskFlowTrainModel
/**
* Navigates to the next stop in a train
* #return outcome string
*/
public String navigateNextStop() {
String nextStopAction = null;
ControllerContext controllerContext = ControllerContext.getInstance();
ViewPortContext currentViewPortCtx = controllerContext.getCurrentViewPort();
TaskFlowContext taskFlowCtx = currentViewPortCtx.getTaskFlowContext();
TaskFlowTrainModel taskFlowTrainModel = taskFlowCtx.getTaskFlowTrainModel();
TaskFlowTrainStopModel currentStop = taskFlowTrainModel.getCurrentStop();
TaskFlowTrainStopModel nextStop = taskFlowTrainModel.getNextStop(currentStop);
//is either null or has the value of outcome
return nextStopAction;
}
Full code of the sample can be found on the ADF Code Corner.
To navigate by taskflow outcomes you just need to provide exact outcome String as return of your method:
private static final String NEXT_NAVIGATION_ACTION = "next";
public String nextAction() {
if (validate()) {
updateModel();
return NEXT_NAVIGATION_ACTION;
}
return null;
}
Can you verify, you can do it in through phase listener.
Verify you condition in the phase listener and allow it to move ahead if it validates else stop the thread execution.
Below is the sample phase listener code.
public class MyPhaseListener implements PagePhaseListener{
public MyPhaseListener() {
super();
}
#Override
public void afterPhase(PagePhaseEvent pagePhaseEvent) {
if (pagePhaseEvent.getPhaseId() == Lifecycle.PREPARE_RENDER_ID ) {
// DO your logic here
}
}
#Override
public void beforePhase(PagePhaseEvent pagePhaseEvent) {
}
}

Saving CheckboxGroup values XPages

I am working on my first Notes/XPages/Java application and I am stuck at some of the basic 'crud' level. The following is part of the managed bean. I can load the data on to the XPage, but saving the Checkbox field is causing me problems, i.e. it won't save. I assume it is to do with the data type as the CheckboxGroup is multivalued.
Form Fields are:
Category
Employment Role
Variables
public class TrainingModule implements Serializable {
private String Category;
private Object EmploymentRole;
public String getCategory() {
return Category; }
public void setCategory(final String category) {
Category = category;}
public Object getEmploymentRole() {
return EmploymentRole;}
public void setEmploymentRole(final Object employmentRole) {
EmploymentRole = employmentRole;}
Load Method
public void load(final String unid) {
setUnid(unid);
Document doc = null;
try {
doc = ExtLibUtil.getCurrentDatabase().getDocumentByUNID(getUnid());
setCategory(doc.getItemValueString("Category"));
setEmploymentRole(doc.getItemValue("EmploymentRole"));
etc
Save Method
public boolean saveData() {
boolean result = false;
Document doc = null;
try {
doc.replaceItemValue("Category", Category);
doc.replaceItemValue("EmploymentRole", EmploymentRole);
result = doc.save()
etc
XPage
<xp:checkBoxGroup id="checkBoxGroup1"
value="#{TrainingModule.employmentRole}">
<xp:selectItem itemLabel="Admin" itemValue="Admin">
</xp:selectItem>
<xp:selectItem itemLabel="Installation" itemValue="Installation">
</xp:selectItem>
<xp:selectItem itemLabel="Proj Man" itemValue="Proj Man">
</xp:selectItem>
</xp:checkBoxGroup>
I know there are similar postings, but I just can't seem to relate them to what I am trying to achieve.
My next task will be using upload and download controls with Java so any hints or traps to avoid would be great.
Any help would be appreciated.
Define your employment roles as a field of type ArrayList<String>:
private List<String> employmentRoles = new ArrayList<String>();
public void setEmploymentRoles(List<String> employmentRoles) {
this.employmentRoles = employmentRoles;
}
public List<String> getEmploymentRoles() {
return employmentRoles;
}
Read the values with
setEmploymentRoles(doc.getItemValue("EmploymentRole"));
and save the values with
doc.replaceItemValue("EmploymentRole", new Vector(getEmploymentRoles()));
Btw, you shouldn't start a field name with a capital letter. Look here for Java naming conventions.
Since you need to load/save your data, you might be better off with an object data source. Anyway try this:
public Object[] getEmploymentRole() {
return EmploymentRole;}
public void setEmploymentRole(final Object[] employmentRole) {
EmploymentRole = employmentRole;}
An array can't be cast to an Object and a checkboxgroup tries to get/set an array.
This then leads to a slight change in your save method:
doc.replaceItemValue("Category", Category);
Vector v = new Vector(Arrays.asList(EmploymentRole));
doc.replaceItemValue("EmploymentRole", v);
Let us know how it goes

How to specify command attribute in h:inputText?

I have a function that I derclare beans in my manager and I want to return the value in inputText but when I put the name of my function in the value attribute of inputText tag like this:
<p: inputText value = "#{ticketBean.getLastIndexTache} "/>
this error appear:
Etat HTTP 500 - /pages/test.xhtml #13,106 value="#{ticketBean.getLastIndexTache}": Property 'getLastIndexTache' not found on type com.bean.TicketBean
here is the java code
#ManagedBean(name="ticketBean")
public class TicketBean {
public int getLastIndexTache() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
int index = 0;
try {
session.beginTransaction();
String sql = "select MAX(t.IDTICKET) from ticket t ";
Query query = session.createSQLQuery(sql);
if( query.uniqueResult()==null){
index=0;
}else{
index=(int) query.uniqueResult();
index=index+1;
}
} catch (HibernateException e) {
// TODO: handle exception
session.getTransaction().rollback();
e.printStackTrace();
}
return index;
}
}
You should use the bean property in value like
<p:inputText value="#{ticketBean.lastIndexTache}"/>
as JSF by itself adds "get" to the property name. Currently it will look for the method getGetLastIndexTache().
Besides its very bad practice to have logic in any getter as they are called multiple times by JSF. Instead you should make an property like
private Integer lastIndexTache; // +getter/setter
and set the value in a #PostConstruct method:
#PostConstruct
public void init() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
// etc....
lastIndexTache = index;
}
The getter would then simply be
public Integer getLastIndexTache() {
return lastIndexTache;
}
and don't forget a setter:
public void setLastIndexTache(Integer newValue) {
lastIndexTache = newValue;
}
Also you should probably put a scope on the bean (for example #ViewScoped).

BeanELResolver #Override getValue(ELContext context, Object base, Object property)

I have
public class ExtendedBeanELResolver extends BeanELResolver {
private static final Pattern regExpDn = Pattern.compile("PLMN-PLMN/\\w+.\\d+(.*)");
#Override
public Object getValue(ELContext context, Object base, Object property)
try {
// remake DIST.NAME appearance
if (property.equals("dn") && base instanceof Alarm && ((Alarm) base).getCustomer().getNameEng().equalsIgnoreCase("mts")) {
String dn = null;
try {
dn = ((Alarm) base).getDn();
Matcher mtch = regExpDn.matcher(dn);
mtch.find();
((Alarm) base).setDn(mtch.group(1));
} catch (Throwable e) {
// logger.error("error in dn - " + dn);
} finally {
return super.getValue(context, base, property);
}
}
}
for change some visible values in object depending on some conditions. I do not want to change value if this called from jsf <ui:param name="fullDistName" value="#{alarm.dn}" />
How i can get id of component from which this EL called?
sorry for my english.
You can get the current JSF component by programmatically evaluating #{component} or by invoking UIComponent#getCurrentComponent().
UIComponent component = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance();
// ...
Please note that this tight-couples your EL resolver to JSF.

Resources