Saving CheckboxGroup values XPages - 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

Related

How to retrieve data from field with multiple="true" in AEM's WorkflowProcess?

Sorry if this is a basic question, as I am quite new to AEM.
I have a cq dialog allowing multiple tags to be entered.
<tags
cq:showOnCreate="{Boolean}true"
jcr:primaryType="nt:unstructured"
sling:resourceType="/libs/cq/gui/components/coral/common/form/tagfield"
allowCreate="{Boolean}true"
fieldLabel="Tags to add"
metaType="tags"
multiple="true" <====================
name="./metaData/TAGS"/>
I am trying to retrieve the two tags above in my WorkflowProcess as below:
#Component(
//...
)
public class TagStep implements WorkflowProcess {
#Override
public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap processArguments) {
try {
//...
List<String> tagslist = new ArrayList();
List<String> tags = processArguments.get("TAGS",tagslist);
// Nothing logged here <=======
for (String tag: tags) {
LOG.info(tag);
}
//...
} catch (Exception e){
LOG.info("\n ERROR {} ",e.getMessage());
}
}
}
There is no output when I try to log tag in the loop above, probably the return type of List<String> cannot be converted.
What is the proper return type when using multiple="true", and how to use processArguments.get to get the values?
Btw my code was based on the tutorial here.
Thank you,
After looking into the source implementation, it is using an Array, not a List. so here is how to retrieve the passed in data.
Node node = (Node) session.getItem(path);
String[] cars = {};
String[] tags = processArguments.get("TAGS",cars);
node.setProperty("cq:tags", tags);

PrimeFaces primeDateRangeValidator - Get variable

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");

Is there a easy way to customize Acumatica build-in dropdown list?

For example, in screen CR301000, source field is having 5 items right now, but I want to have 6 different items listing here, please advice how to do it. Thanks.
You can do it a few ways.
1) Customization to create a custom string/int list then override the dac attribute in the BLC to point to your custom list.
First create the custom stringlist:
public class CustomSourceAttribute : PXStringListAttribute
{
public const string _LEADPROSPECT = "1";
public const string _INITIALCONTACT = "2";
public const string _QUALIFIED = "3";
public const string _INITIALPRICE = "4";
public const string _PROPOSALSENT = "5";
public const string _POSITIVEPROPOSAL = "6";
public const string _VERBALCOMMIT = "7";
public const string _READYFORCONTRACT = "R";
public const string _CONTRACTSENT = "8";
public const string _CONTRACTSIGNED = "9";
public const string _CLOSEDLOST = "0";
public const string _TARGET = "T";
public CustomSourceAttribute()
: base(new string[]
{
_LEADPROSPECT,
_INITIALCONTACT,
_QUALIFIED,
_INITIALPRICE,
_PROPOSALSENT,
_POSITIVEPROPOSAL,
_VERBALCOMMIT,
_READYFORCONTRACT,
_CONTRACTSENT,
_CONTRACTSIGNED,
_CLOSEDLOST,
_TARGET
},
new string[]
{
"Lead/Prospecting",
"Initial Contact",
"Qualified",
"Initial Pricing Sent",
"Proposal Sent",
"Positive Proposal Discussions",
"Verbal Commitment",
"Ready for Contract",
"Contract Sent",
"Contract Signed",
"Closed Lost",
"Target"
})
{
}
}
Then override the dac attribute in a BLC Extension:
[PXDBString(1, IsFixed = true)]
[PXUIField(DisplayName = "Stage")]
[CustomSourceAttribute]
[PXDefault(CustomSourceAttribute._INITIALCONTACT)]
[PXMassUpdatableField]
protected void CROpportunity_StageID_CacheAttached(PXCache cache)
{
}
This sample is from the Opportunity screen but the same holds true w/ leads
2) Automation step to provide the new values.
See here for automation step locations
the second way doesn't require customization but does take more work if there is already automation steps defined. You need to create the custom list for each step that exists.
For something like Leads, I'd go with option 1 as there is tons of steps
Add the Values you want:
Just a quick note if you chose to add via automation - to add a new field click in the white space of the lookup field - You will see the current values - in the white space below - dbl click.
Here is an example of creating Acumatica dropdown list field. Add constatnt fields and Pair them in Tuple<T1, T2>[].
public class Operators
{
public const string And = "&&";
public const string Or = "||";
public class UI
{
public const string And = "And";
public const string Or = "Or";
}
public class OperatorsAttribute : PXStringListAttribute
{
public OperatorsAttribute() : base(new Tuple<string, string>[]
{
Pair(And, UI.And),
Pair(Or, UI.Or)
})
{}
}
}
Then you use the nested OperatorsAttribute attribute class on the field like this.
#region Operator
public abstract class operators : BqlString.Field<operators> { }
[PXDBString(15)]
[PXDefault(1)]
[OperatorsAttribute]
[PXUIField(FieldName = "Operators", DisplayName = "Operators")]
public virtual string Operators { get; set; }
#endregion
To change already existing fields, create Extension classes for DACs and Graphs. Here is the detailed documentation for creating extension classes — Acumatica ERP Customization Guide

Add new property in subsonic partial class

I added a new column(DateCreated) in a table(Activity) in sqlserver.
and I am using subsonic 2.0, how can I add this column as property in subsonic partial class, so that I can insert and update the value of "DateCreated" Column.
DateCreated will be provided by the user from the GUI.
following is the code I m using but it insert NULL & retrive NULL from the database.
public partial class ActivityInscription
{
public struct Columns
{
public static string IsInMixedList = #"IsInMixedList";
}
public bool? IsInMixedList
{
get;
set;
}
}
Please any one help me to resolve this issue.
If you added the column to the database then just rebuild the DAL. It will pick up the new column and add it to the subsonic DAL. There is no reason for a Partial class in your case. This will work providing that the table "Activity" is part of your subsonic list (includeTableList) of tables in the config file.
Following is the solution, I used and it is working:
public partial class Activity
{
public DateTime? DateCreated
{
get;
set;
}
protected override void BeforeInsert()
{
TableSchema.Table tblSchema = Schema;
TableSchema.TableColumn ccDateCreated = new TableSchema.TableColumn(tblSchema);
ccrDateCreated.ColumnName = "DateCreated";
ccDateCreated.DataType = DbType.DateTime;
ccDateCreated.MaxLength = 0;
ccDateCreated.AutoIncrement = false;
ccDateCreated.IsNullable = false;
ccDateCreated.IsPrimaryKey = false;
ccDateCreated.IsForeignKey = false;
ccDateCreated.IsReadOnly = false;
ccDateCreated.DefaultSetting = #"";
ccDateCreated.ForeignKeyTableName = "";
if (!tblSchema.Columns.Contains("DateCreated"))
{
tblSchema.Columns.Add(ccDateCreated);
}
if (this.GetSchema().Columns.Contains("DateCreated"))
this.SetColumnValue(Columns.DateCreated, DateCreated);
base.BeforeInsert();
}
}
Now it is working fine & inserting the values that I provide from the GUI.

SharePoint 2007 (wss) search and Unable to validate data Exception

We have a problem with SharePoint's search box. Whenever we try to search for something we get:
Unable to validate data. at
System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean
fEncrypt, Byte[] buf, Byte[] modifier,
Int32 start, Int32 length, IVType
ivType, Boolean useValidationSymAlgo)
at
System.Web.UI.ObjectStateFormatter.Deserialize(String
inputString) exeption.
Does any one know the reason for this exception, or a way to work around it?
New entry:
I'm using a SPGridView where i use the datakeys property in a web part. The webpart works, but we found that using the datakeys property breaks seach in that if you try to use the search textbox and click the seach button it gets this exception:
Unable to validate data. at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
This is what i have tryed to do:
Make the gridview not spgridview and set autogenerate true (works)
Remove the datakeynames (works)
Test with a empty gridvew (failes)
Test with a non-empty gridview (failes)
Change Machine Keys (failes)
Turn of view state on the gridvew (failes)
Move the gridview ti a ascx file (failes)
I can't seem to figure this one out. Have enyone got this error and been able to work around it?
EDit 10.09.2009
This is the last code I tested. I used a MSDN excample as referance. I have also tried without Data table MSDN Example
public class TestErrorGridView : System.Web.UI.WebControls.WebParts.WebPart
{
Control ascxToAdd;
protected DataTable PropertyCollection = new DataTable();
private DataColumn key;
public TestErrorGridView()
{
key = PropertyCollection.Columns.Add("ID", typeof(string));
PropertyCollection.Columns.Add("Name", typeof(string));
}
public void AddProperty(TestBindObject data)
{
DataRow newRow = PropertyCollection.Rows.Add();
newRow["ID "] = data.ID;
newRow["Name"] = data.Name;
}
public void BindGrid(SPGridView grid)
{
SPBoundField fldPropertyName = new SPBoundField();
fldPropertyName.HeaderText = "ID";
fldPropertyName.DataField = "ID";
grid.Columns.Add(fldPropertyName);
SPBoundField fldPropertyValue = new SPBoundField();
fldPropertyValue.HeaderText = "Name";
fldPropertyValue.DataField = "Name";
grid.Columns.Add(fldPropertyValue);
PropertyCollection.PrimaryKey = new DataColumn[] { key };
grid.DataSource = PropertyCollection.DefaultView;
grid.DataKeyNames = new string[] { key.ColumnName };
grid.DataBind();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
TestBindObject t1 = new TestBindObject() { ID = 1, Name = "Test3" };
this.AddProperty(t1);
SPGridView testGrid = new SPGridView() { AutoGenerateColumns = false };
this.BindGrid(testGrid);
this.Controls.Add(testGrid);
}
}
[Serializable]
public class TestBindObject
{
public int ID { get; set; }
public string Name { get; set; }
}
From the error message I'd say that you are operating in a web-farm environment. Have you set the same machineKey in each of the SharePoint web.config files? See this link for a little more info.

Resources