I have a fixed-length stream containing record counters
Records starts with Z
Characters 16+9 (human form) contain B record counter
Characters 25+9 (human form) contain C record counter
All numbers padded with 0 and aligned to the right
Record ends with A + CRLF at position 1898 (record is long 2000 chars)
Following BeanIO mapping code
<record name="RECORD_Z" class="com.acme.ftt2017.RecordZ" order="4" minOccurs="1" maxOccurs="1" maxLength="1900">
<field name="tipoRecord" rid="true" at="0" ignore="true" required="true" length="1" lazy="true" literal="Z" />
<field name="numeroRecordB" at="15" length="9" padding="0" align="right" trim="true" />
<field name="numeroRecordC" at="24" length="9" padding="0" align="right" trim="true" />
<field name="terminatorA" at="1897" length="1" rid="true" literal="A" ignore="true" />
</record>
Bean
public class RecordZ implements Serializable
{
private final char tipoRecord = 'Z';
private Integer numeroRecordB, numeroRecordC;
// G & S omitted
}
I have triple-checked in debug the following code:
RecordZ trailer = new RecordZ();
trailer.setNumeroRecordB(1);
trailer.setNumeroRecordC(countRecordC); // equals 1 in debug
log.debug("Exporting record Z");
log.trace("Record Z: " + trailer.toString());
exporter.write(FttRecordTypes.RECORDTYPE_FTT_Z, trailer);
However the produced data file contains the following
Z 000000000000000000 A
Expected
Z 000000001000000001 A
What is wrong with my export code? Why am I getting always zeroes?
From the last paragraph in Section 4.3.1
Optionally, a format attribute can be used to pass a decimal format for java.lang.Number types, and for passing a date format for java.util.Date types. In the example below, the hireDate field uses the SimpleDateFormat pattern "yyyy-MM-dd", and the salary field uses the DecimalFormat pattern "#,##0". For more information about supported patterns, please reference the API documentation for Java's java.text.DecimalFormat and java.text.SimpleDateFormat classes.
And in Section 4.3.2
A type handler may be explicitly named using the name attribute, and/or registered for all fields of a particular type by setting the type attribute. The type attribute can be set to the fully qualified class name or type alias of the class supported by the type handler. To reference a named type handler, use the typeHandler field attribute when configuring the field.
Thus, You can try one of 2 things:
Remove the use of your custom *IntegerTypeHandlers and specify a format attribute on the fields which use these custom type handlers. This might be a lot of work depending on the amount of fields and type handlers you have. For example:
<field name="numeroRecordB" format="000000000" at="15" length="9" padding="0" align="right" trim="true" />
OR
Make the getType() method return null instead of Integer.class in your custom type handlers, this will hopefully then not be used as a global type handler. I haven't done this before, so it might not work.
public Class<?> getType() {
return null;
}
Hope this helps.
Discovered the guilty. The custom type handlers!!!!
According to BeanIO
A type handler may be explicitly named using the name attribute, and/or registered for all fields of a particular type by setting the type attribute. The type attribute can be set to the fully qualified class name or type alias of the class supported by the type handler. To reference a named type handler, use the typeHandler field attribute when configuring the field.
So I did not show that in the heading of my file I have registered plenties of custom type handlers, unfortunately all with a type attribute.
<typeHandler name="int_2" type="java.lang.Integer" class="org.beanio.types.IntFixedLengthTypeHandler">
<property name="numberOfDigits" value="2" />
</typeHandler>
<typeHandler name="int_4" type="java.lang.Integer" class="org.beanio.types.IntFixedLengthTypeHandler">
<property name="numberOfDigits" value="2" />
</typeHandler>
<typeHandler name="int_10" type="java.lang.Integer" class="org.beanio.types.IntFixedLengthTypeHandler">
<property name="numberOfDigits" value="10" />
</typeHandler>
<typeHandler name="bigint_16" type="java.math.BigInteger" class="org.beanio.types.BigIntFixedLengthTypeHandler">
<property name="numberOfDigits" value="16" />
</typeHandler>
Removing the type attribute works
Related
The requirement is to skip field when its empty.
eg -
<segment name="seg1" class="com.company.bean.segmentBean" xmlType="none">
<field name="field1" xmlName= "fieldXml1" xmlType="attribute" maxLength="7" />
<field name="field2" xmlName= "fieldX2l1" xmlType="attribute" maxLength="1" typeHandler="Handler" />
</segment>
Lets assume that field2="". As the value of field2 is "". I would like to have the field skipped in segment. Basically the end result XML shouldnt display field2 as its empty("").
You need the lazy attribute on field2. As stated in the Reference Guide
lazy - Set to true to convert empty field text to null before type conversion. For repeating fields bound to a collection, the collection will not be created if all field values are null or the empty String. Defaults to false.
This will make field2 = null and by default, most XML libraries will not output any null elements, BeanIO included.
Try this for field2:
<field name="field2" lazy="true" xmlName= "fieldX2l1" xmlType="attribute" maxLength="1" typeHandler="Handler" />
Most of the time, I also combine lazy with trim. From the docs:
trim - Set to true to trim the field text before validation and type
conversion. Defaults to false.
<field name="field2" lazy="true" trim="true" xmlName= "fieldX2l1" xmlType="attribute" maxLength="1" typeHandler="Handler" />
I'm trying to setup faceting through Solr. I have a specific field to use called "Category". The faceting works, but appears lowercase and only contains a single word. I'm sure this is due to the field analyzer so I've change the field's type to "string". This produces a error! See below.
FYI - I'm using Solr 4.3.
You can see the fieldtype and the field below. You can see the field is set to the fieldtype "string". This field type uses "Solr.StrField". Why would using this fieldtype cause the error below?
Schema.xml
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
</types>
<fields>
<field name="category" type="string" indexed="true" stored="true"
required="false" multiValued="false"/>
</fields>
I'm getting the error message in the log and when attempting to run a query
This AttributeSource does not have the attribute
'org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute'
null:java.lang.IllegalArgumentException: This AttributeSource does not
have the attribute
'org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute'.
Update:
Since the error seems to indicate that my fieldtype should have the attribute PositionIncrementAttribute, I added to my string to test. I then cleared and re-indexed, but still no luck.
<fieldType name="string" class="solr.StrField" sortMissingLast="true"
positionIncrementGap="100"/>
I have a xml and have to validate against xsd for the structure and data type. but Some fields in the xml has null/empty values. But when using JAXB for validating the xml
"cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'."
This exception is thrown from JAXB exception with linked SaxParserError Exception. But I have to accept the xml with null values. These threads
validating an XML schema with empty attributes and Element type(long) without content shows we have to modify the xml with respect to xsd such that it should accept the null/empty values.
Is there any other way that I can override the methods of ValidationHandler class and Unmarshaller class to accept null values.
Well I guess you tried to put
<myinteger></myinteger>
in your XML but have an XSD like:
<element name="myinteger" type="integer" />
or
<element minOccurs="0" name="myinteger" type="integer" />
JAXB is right. In terms of XSD validation, this is wrong so you either have to change the XML, change the XSD, or disable validation (will still be wrong but won't crash). MinOccurs="0" means it is accepted that the element is not present at all (remove all the myinteger tags). It doesn't mean that a tag with empty content is accepted. The content must be integer. Empty string is not an integer.
Setting nillable = true doesn't work either. It means that this would be accepted :
<myinteger xsi:nil="true"></myinteger>
But you have to add this xsi:nil="true".
If you do want to accept this:
<myinteger></myinteger>
You can change your XSD as below:
<element name="myinteger" type="IntegerOrNothing" />
<xsd:simpleType name="IntegerOrNoting">
<xsd:union memberTypes="xsd:integer">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="" />
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
If you generate your beans from the XSD with Jaxb, fields of this type will be of type String by default. You will then need to use custom bindings to get Integer fields.
I'm experiencing a little issue and I'm asking for your help!
Using BeanIO 2.1 and working on a fixed-length file, I'm currently trying to retrieve a record that is structured like this :28C:5n/5n
':28C:' : fix
5 numbers (maximum)
'/' : fix
5 numbers (maximum)
Examples:
:28C:61/00005
:28C:100/00001
:28C:12345/12345
Here is a snippet of the code:
<record name="statementNumber" class="com.batch.records.StatementNumber" occurs="1">
<field name="tag" type="string" length="5" rid="true" literal=":28C:" ignore="true" />
<field name="statementNr" type="int" length="unbounded" maxLength="5" />
<field name="separator" type="string" length="1" rid="true" literal="/" ignore="true" />
<field name="sequenceNr" type="int" length="unbounded" maxLength="5" />
</record>
When running my parser, I get this exception:
Cannot determine field position, field is preceded by another component with indeterminate occurrencesor unbounded length
My question is: how can I tell BeanIO that the field '/' is actually the delimiter between the two variable fields ?
Thanks in advance
You can only have 1 field of an unbounded length on a line. The BeanIO documentation says:
The length of the last field in a fixed length record may be set to unbounded to disable padding and allow a single variable length field at the end of the otherwise fixed length record.
Honestly, I'm not sure if this can be done using BeanIO. Is it an option to read the 5n/5n fields completely into Java as 1 field and splitting it on / in your code, instead of BeanIO?
Could someone tell me the difference between this two property definitions?
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="blablaService">
<property name="dbUrl" type="String">jdbc:h2:url</property>
<property name="dbUser" type="String" value="user" />
</scr:component>
I'm using Dictionary properties = context.getProperties(); to get the values. It seems to be that if the property given surround with xxx is treated as an Object holding a String[1] and the property which value is specified in the value attribute is treated as an Object which is de facto a String. For the first example (String) throws and Exception as the latter does not.
I'm developing using Eclipse and the Component Context is from org.osgi.service.component.ComponentContext.
<property name="dbUser" type="String" value="user" /> yields a scalar String.
<property name="dbUrl" type="String">jdbc:h2:url</property> yields a String[1].
This is per the spec. See 112.4.6 in the Compendium Spec.