How to remove xml namespace declaration using dom4j? - xpath

I am using dom4j and xpath to parse a xml file,and I met a question: if there is an xmlns declaration,then xPath will return nothing,however,if the namespace declaration is removed,then xPath works fine,and will reutrn the expected value.
Here is my java test file:
public class XPathTest {
public static void main(String[] args) {
testXPath();
}
public static void testXPath(){
Document doc=getDocument("file/info.xml");
Element root=doc.getRootElement();
/*boolean removeFlag=root.remove(root.getNamespace());
System.out.println("removeFlag:\t"+removeFlag);*/
Node node=root.selectSingleNode("list[#id='002']/name");
System.out.println(node.getText());
}
public static Document getDocument(String file){
Document document=null;
SAXReader saxReader=null;
try {
saxReader=new SAXReader();
document= saxReader.read(new File(file));
} catch (DocumentException e) {
e.printStackTrace();
}
return document;
}
}
Here is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<info xmlns="http://fit42.sys42.vwg/emx">
<intro>信息</intro>
<list id='001'>
<head>auto_userone</head>
<name>Jordy</name>
<number>12345678</number>
<age>20</age>
<sex>Man</sex>
<hobby>看电影</hobby>
</list>
<list id='002'>
<head>auto_usertwo</head>
<name>tester</name>
<number>34443678</number>
<age>18</age>
<sex>Man</sex>
<hobby>玩游戏</hobby>
</list>
<taichung id='003'>
<mayor>Jason Hu</mayor>
</taichung>
</info>
When I run my test program,I got a NullPointerException stack.However,if I remove the namespace declaration for the xml and make it as below,then everything works fine:
<?xml version="1.0" encoding="utf-8"?>
<info>
<intro>信息</intro>
<list id='001'>
<head>auto_userone</head>
<name>Jordy</name>
<number>12345678</number>
<age>20</age>
<sex>Man</sex>
<hobby>看电影</hobby>
</list>
<list id='002'>
<head>auto_usertwo</head>
<name>tester</name>
<number>34443678</number>
<age>18</age>
<sex>Man</sex>
<hobby>玩游戏</hobby>
</list>
<taichung id='003'>
<mayor>Jason Hu</mayor>
</taichung>
</info>
But due to the xml file is get from other companies and I can not modify the structure of it,so I tried to remove the namespace declaration in my progaram,I modified the testXPath method as below,the remove action return true and I still can see the xml declaration in the rootElement,so the program still generate a NullPointerException,I do not know why:
public static void testXPath(){
Document doc=getDocument("file/info.xml");
Element root=doc.getRootElement();
boolean removeFlag=root.remove(root.getNamespace());
System.out.println("removeFlag:\t"+removeFlag);
Node node=root.selectSingleNode("list[#id='002']/name");
System.out.println(node.getText());
}
So my question is:could anyone give me some advice on how to solve it?

hy,
your problem is in xPath, if the element name or attribute has name with caratere utf8 or in your xml you have speciefied a NameSpace you must use function in xPath.
this is code work:
public static void main(String[] args) {
testXPath();
}
public static void testXPath() {
Document doc = getDocument("C:\\test\\test.xml");
if (doc != null) {
Element root = doc.getRootElement();
Element element = (Element) root.selectSingleNode("./*[name()='list'][#id='002']/*[name()='name']");
if (element != null) {
System.out.println(element.asXML());
}
else {
System.out.println("element not found");
}
}
else {
System.out.println("File XML not found/ Error parse XML file");
}
}
public static Document getDocument(String pathname) {
Document document = null;
SAXReader saxReader = null;
try {
saxReader = new SAXReader();
document = saxReader.read(new File(pathname));
}
catch (DocumentException e) {
e.printStackTrace();
}
return document;
}

Related

Reading XML Files using Java, return in a SOAP request

I'm fairly new to using SOAP and Blueprint (Which is just like Spring).
Anyway, I'm just trying to learn the basics atm, doing pretty well so far.
I've run into a small problem when using a Java Class to retrieve a specific node value from an XML file. This works when I run the application as a stand-alone but when I am getting the request using Soap, the value "lastName" returns null.
public static void main(String[] args) throws XPathExpressionException {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException p) {
p.printStackTrace();
}
try {
Document document = builder.parse(new FileInputStream("d:\\input11.xml"));
XPath xP = XPathFactory.newInstance().newXPath();
String expression ="/people/person/lastName";
NodeList nodeList = (NodeList) xP.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
lastName += nodeList.item(i).getFirstChild().getNodeValue() + " ";
}
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException s) {
s.printStackTrace();
}
System.out.println(lastName);
}
public static String returnLastName(String input){
System.out.println(lastName);
return "LastName: "+lastName +"\n";
}
}
And here's my blueprint.xml code:
<bean id="lastNameBean" class="com.*****.camelBlueprintTest.XMLCamel" />
<route id="lastName">
<from uri="cxf:bean:returnLName" />
<bean ref="lastNameBean" method="returnLastName" />
<log message="The message contains ${body}" />
<to uri="mock:result" />
</route>
So it does actually return the last names when I run the Java application, but in the SOAP request I am getting "LastName: null".
AH!! I've found the error. Silly me. So, I was calling the method in my blueprint "returnLastName" and it was returning null, I didn't realize that this method was called ALONE, so moving my code from the main into the method fixed it like a charm haha.
I feel really silly but it's always the little mistakes that get me.

How to externalize the queries to xml files using spring

I am using spring and their JDBC template to do read/write operations to the database. I am facing a problem in my reporting module that i have to frequently change the query sqls to cater to frequent changes.
Though using spring jdbc ORM, is there a way to externalize my query parameters such that i just change it in the XML & restart and there is no need to rebuild my source again for deployment. Any approach ORM (preferred) or simple Sql will do.
As of now i have to change the query again and again ,rebuild the source and deploy.
I am not sure if Spring provides some out of the box solutions to implement what you want. But here is one way to get it done, which i had implemented ones. So i will try to reduce some hardwork for you.
You might need to implement a utility to load from resources xml file. Something like this.
public final class LoadFromResourceFileUtils {
public static String loadQuery(final String libraryPath,
final String queryName) {
final InputStream is = StreamUtils
.streamFromClasspathResource(libraryPath);
if (is == null) {
throw new RuntimeException(String.format(
"The SQL Libary %s could not be found.", libraryPath));
}
final Document doc = XMLParseUtils.parse(is);
final Element qryElem = (Element) doc.selectSingleNode(String.format(
"SQLQueries/SQLQuery[#name='%s']", queryName));
final String ret = qryElem == null ? null : qryElem.getText();
return ret;
}
}
You would need to store your queries in an XML say queries.xml and keep it in your classpath, for e.g
<?xml version="1.0" encoding="UTF-8"?>
<SQLQueries>
<SQLQuery name="myQuery">
<![CDATA[
your query
]]>
</SQLQuery>
</SQLQueries>
And in your DAO you can do this to get the query
String query = LoadFromResourceFileUtils.loadQuery(
"queries.xml", "myQuery");
XMLParseUtils and StreamUtils for your reference
public final class XMLParseUtils {
public static Document parse(final InputStream inStream) {
Document ret = null;
try {
if (inStream == null) {
throw new RuntimeException(
"XML Input Stream for parsing is null");
}
final SAXReader saxReader = new SAXReader();
ret = saxReader.read(inStream);
} catch (final DocumentException exc) {
throw new RuntimeException("XML Parsing error", exc);
}
return ret;
}
}
public final class StreamUtils {
public static InputStream streamFromClasspathResource(
final String resourceClassPath) {
final Class<StreamUtils> clazz = StreamUtils.class;
final ClassLoader clLoader = clazz.getClassLoader();
final InputStream inStream = clLoader
.getResourceAsStream(resourceClassPath);
if (inStream == null) {
if(LOGGER.isDebugEnabled()){
LOGGER.debug(String.format("Resource %s NOT FOUND.",
resourceClassPath));
}
}
return inStream;
}
}

How to make VSIX installer to register assembly automatically

I have developed a custom code generator and deploy it via a VSIX, the problem is I should register assembly via regasm.exe after installing VSIX, but I have seen some projects such as DSLTool with custom code generation that registers automatically, any body knows how can I have automatically registration in my VSIX project?
You should be able to do the following:
0. Remove old (bad practice) COM code
Edit your project build settings to not have "Register for COM interop" checked.
Edit your AssemblyInfo.cs and set ComVisible to false:
[assembly: ComVisible(false)]
Assuming your generator is named MyCodeGenerator, open the definition of MyCodeGenerator and add the attribute:
[ComVisible(true)]
1. Edit your VSIX project to enable generation of a pkgdef file.
Right click your project in Solution Explorer and select Unload Project.
Right click the unloaded project and select Edit MyProject.csproj, where MyProject is the name of your project.
Locate the XML element <GeneratePkgDefFile>.
If the element exists, ensure that its value is set to true.
Otherwise, add the following to the end of the first <PropertyGroup> element in your project file which does not have a Condition attribute (this is almost always the first PropertyGroup in the file).
<GeneratePkgDefFile>true</GeneratePkgDefFile>
Repeat step 3 to set <CopyBuildOutputToOutputDirectory> to true.
Save and close the .csproj file.
Right click the unloaded project in Solution Explorer and select Reload Project.
Open your project's source.extension.vsixmanifest file and locate the <Content> element. Add the following element as a child:
<VsPackage>|%CurrentProject%|</VsPackage>
If your extension does not provide any other content elements, the entire <Content> element would now be this:
<Content>
<VsPackage>|%CurrentProject%|</VsPackage>
</Content>
2. Define the required attribute types
At the end of this answer are sections for ProvideGeneratorAttribute.cs and ProvideAssemblyObjectAttribute.cs. Add these files to your project.
3. Register the code generator class
Open your project's AssemblyInfo.cs.
Assuming your custom code generator class is named MyCodeGenerator, add the following attribute to the assembly info file.
[assembly: ProvideAssemblyObject(typeof(MyCodeGenerator))]
4. Associate your code generator with the language service
Open your project's AssemblyInfo.cs.
Assuming your custom code generator class is named MyCodeGenerator, and you want to register the code generator with the C# language service, add the following attribute to the assembly info file.
[assembly: ProvideGenerator(
typeof(MyCodeGenerator),
VSConstants.UICONTEXT.CSharpProject_string,
Description = "Description of the generator",
GeneratesDesignTimeSource = true)]
Appendix A: ProvideGeneratorAttribute.cs
Disclaimer: This code is completely untested.
using System;
using Microsoft.VisualStudio.Shell;
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class ProvideGeneratorAttribute : RegistrationAttribute
{
private readonly Type _generatorType;
private readonly Guid _languageServiceGuid;
private string _name;
private string _description;
private bool _generatesDesignTimeSource;
public ProvideGeneratorAttribute(Type generatorType, string languageServiceGuid)
{
if (generatorType == null)
throw new ArgumentNullException("generatorType");
if (languageServiceGuid == null)
throw new ArgumentNullException("languageServiceGuid");
if (string.IsNullOrEmpty(languageServiceGuid))
throw new ArgumentException("languageServiceGuid cannot be empty");
_generatorType = generatorType;
_languageServiceGuid = new Guid(languageServiceGuid);
_name = _generatorType.Name;
}
public Type GeneratorType
{
get
{
return _generatorType;
}
}
public Guid LanguageServiceGuid
{
get
{
return _languageServiceGuid;
}
}
public string Name
{
get
{
return _name;
}
set
{
if (value == null)
throw new ArgumentNullException("value");
if (string.IsNullOrEmpty(value))
throw new ArgumentException("value cannot be empty");
_name = value;
}
}
public string Description
{
get
{
return _description;
}
set
{
_description = value;
}
}
public bool GeneratesDesignTimeSource
{
get
{
return _generatesDesignTimeSource;
}
set
{
_generatesDesignTimeSource = value;
}
}
private string RegistrationKey
{
get
{
return string.Format(#"Generators\{0}\{1}", LanguageServiceGuid.ToString("B"), Name);
}
}
public override void Register(RegistrationContext context)
{
using (Key key = context.CreateKey(RegistrationKey))
{
if (!string.IsNullOrEmpty(Description))
key.SetValue(string.Empty, Description);
key.SetValue("CLSID", GeneratorType.GUID.ToString("B"));
key.SetValue("GeneratesDesignTimeSource", GeneratesDesignTimeSource ? 1 : 0);
}
}
public override void Unregister(RegistrationContext context)
{
context.RemoveKey(RegistrationKey);
}
}
Appendix B: ProvideAssemblyObjectAttribute.cs
Disclaimer: This code is completely untested.
using System;
using Microsoft.VisualStudio.Shell;
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class ProvideAssemblyObjectAttribute : RegistrationAttribute
{
private readonly Type _objectType;
private RegistrationMethod _registrationMethod;
public ProvideAssemblyObjectAttribute(Type objectType)
{
if (objectType == null)
throw new ArgumentNullException("objectType");
_objectType = objectType;
}
public Type ObjectType
{
get
{
return _objectType;
}
}
public RegistrationMethod RegistrationMethod
{
get
{
return _registrationMethod;
}
set
{
_registrationMethod = value;
}
}
private string ClsidRegKey
{
get
{
return string.Format(#"CLSID\{0}", ObjectType.GUID.ToString("B"));
}
}
public override void Register(RegistrationContext context)
{
using (Key key = context.CreateKey(ClsidRegKey))
{
key.SetValue(string.Empty, ObjectType.FullName);
key.SetValue("InprocServer32", context.InprocServerPath);
key.SetValue("Class", ObjectType.FullName);
if (context.RegistrationMethod != RegistrationMethod.Default)
_registrationMethod = context.RegistrationMethod;
switch (RegistrationMethod)
{
case Microsoft.VisualStudio.Shell.RegistrationMethod.Default:
case Microsoft.VisualStudio.Shell.RegistrationMethod.Assembly:
key.SetValue("Assembly", ObjectType.Assembly.FullName);
break;
case Microsoft.VisualStudio.Shell.RegistrationMethod.CodeBase:
key.SetValue("CodeBase", context.CodeBase);
break;
default:
throw new InvalidOperationException();
}
key.SetValue("ThreadingModel", "Both");
}
}
public override void Unregister(RegistrationContext context)
{
context.RemoveKey(ClsidRegKey);
}
}

MyBatis select statement returns null values

I'm trying to run a simple MyBatis example, selecting all rows from the "trains" table.
The problem is that the query performs, but it returns a list with the correct number of elements, but populated with null values.
The same query runned directly with JDBC PreparedStatement works fine.
Perhaps it's a configuration problem, but I cannot figure out what I'm doing wrong.
Here is the code. Thanks in advance.
Train.java
package org.example.mybatis.domain;
public class Train implements Serializable
{
private int id;
private String type;
// getters and setters
}
TrainMapper.java
package org.example.mybatis.persistence;
public interface TrainMapper {
List<Train> getAllTrains();
}
TrainSelector.java
package org.example.mybatis.test;
public class TrainSelector implements TrainMapper {
private static String resource = "mybatis-config.xml";
private static SqlSessionFactory factory = null;
private SqlSessionFactory getSqlSessionFactory()
{
if (factory == null)
{
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
return factory;
}
#Override
public List<Train> getAllTrains()
{
List<Train> trains = null;
SqlSession session = getSqlSessionFactory().openSession();
try {
TrainMapper mapper = session.getMapper(TrainMapper.class);
trains = mapper.getAllTrains();
} finally {
session.close();
}
return trains;
}
public static void main(String[] args) {
List<Train> trains = null;
TrainSelector trainSelector = new TrainSelector();
trains = trainSelector.getAllTrains();
System.out.println(trains);
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="database.properties" />
<typeAliases>
<typeAlias alias="Train" type="org.example.mybatis.domain.Train" />
<!--package name="org.example.mybatis.domain" />-->
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/example/mybatis/persistence/TrainMapper.xml" />
</mappers>
</configuration>
TrainMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mybatis.persistence.TrainMapper">
<cache />
<select id="getAllTrains" parameterType="list" resultType="Train">
SELECT *
FROM trains
</select>
</mapper>
JdbcStatementExample.java
package org.example.mybatis.test;
public class JdbcStatementExample {
private static void selectAllTrains() throws SQLException
{
String sql = "SELECT * FROM trains";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String url = "jdbc:mysql://localhost/testing";
String user = "test";
String password = "test";
try {
conn = DriverManager.getConnection(url, user, password);
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
String id = rs.getString("train_id");
String type = rs.getString("train_type");
System.out.println("id: " + id);
System.out.println("type: " + type);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
}
}
public static void main(String[] args)
{
try {
selectAllTrains();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
The names of the columns in the result set are different from the names of the properties in the Train object. You need an explicit result map to let Mybatis know which column is to be mapped to which property.
<resultMap id="trainMap" type="Train>
<id property="id" column="train_id" javaType="java.lang.Integer" jdbcType="INTEGER"/>
<result property="type" column="train_type" javaType="java.lang.String" jdbcType="VARCHAR"/>
</resultMap>
Making your select element into
<select id="getAllTrains" parameterType="list" resultType="trainMap">
SELECT * FROM trains
</select>
Other option is to use column names an aliases.
The column names will be your database's and the aliases will be set to match with your Train object properties:
<select id="getAllTrains" parameterType="list" resultType="trainMap">
SELECT
train_id as id,
train_type as type
FROM trains
</select>
I had the same problem, but only for fields with multiple words. Of course my naming convention in SQL was user_id and in java was userId. This piece of config inside my mybatis-config.xml file saved the day:
<settings>
<setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>
or for properties file:
mybatis.configuration.map-underscore-to-camel-case=true
credit: https://chois9105.github.io/spring/2017/12/31/configuring-mybatis-underscore-to-camel-case.html
Results can be mapped as described by Seeta or in the official docs here:
https://mybatis.org/mybatis-3/sqlmap-xml.html
In MyBatis 3.x the example doesn't work as you need to set resultMap rather than resultType. And you must not set both at the same time! Working example looks like:
<select id="getAllTrains" parameterType="list" resultMap="trainMap">
SELECT * FROM trains
</select>
if you are using spring boot, you can change the map-underscore-to-camel-case property as true like below. because most if the time we use _ (user_id) when create the table attributes. but in java we use camelCase (userId) for the variables. then mybatis don't know about that and when it tries to mapping, the error is thrown.
mybatis.configuration.map-underscore-to-camel-case=true

Spring integeration - error-channel handling issues

I am new in Spring Integeration.I have one requirement Using spring integeration
read a txt file (from Source folder)
do some validation
if validation is success -write into sucess file (in sucess folder)
If the validation is fail -write into failure file (in error folder)
if the file format is incorrect means I have to move that file into error folder(Ex excepted columns is 2 but in my file contain columns is 1)
My config file is like this
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:si="http://www.springframework.org/schema/integration"
xmlns:file="http://www.springframework.org/schema/integration/file"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
http://www.springframework.org/schema/integration/file
http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd">
<bean id="checkCSVReader"
class="com.check.wrapper">
<property name="pzMapXML" value="classpath:sampleFileFormat.xml" />
</bean>
<bean id="checkTrasnFomer"
class="com.check.checkTransfomer">
<property name="wrapper" ref="checkCSVReader" />
</bean>
<bean id="fileErrorProcessor"
class="com.check.ErrorChannelWriter">
</bean>
<bean id="listToStringTrans"
class="com.check.ListToStringTransfomer"></bean>
<bean id="validation"
class="com.check.Validation"/>
<file:inbound-channel-adapter directory="file://D:\check\soruce" prevent-duplicates="false"
auto-create-directory="true" channel="readChannel" >
<si:poller id="Poller">
<si:interval-trigger interval="10000" />
</si:poller>
</file:inbound-channel-adapter>
<si:channel id="readChannel" />
<si:chain input-channel="readChannel" output-channel="processChannel">
<si:header-enricher error-channel="errorFile" />
<file:file-to-string-transformer />
<si:transformer ref="checkTrasnFomer" method="transform" />
<si:service-activator ref="validation"
method="validate" />
</si:chain>
<si:channel id="processChannel" />
<si:transformer ref="listToStringTrans" method="transformList"
input-channel="processChannel" output-channel="finalOut" />
<si:channel id="finalOut" />
<file:outbound-channel-adapter id="checkSuccFileOutBound"
auto-create-directory="true" delete-source-files="true"
directory="file://D:\check\success" channel="finalOut">
</file:outbound-channel-adapter>
<si:channel id="errorFile" />
<si:transformer ref="fileErrorProcessor"
input-channel="errorFile" output-channel="errorChannel" method="transformError" />
<file:outbound-channel-adapter id="errorChannel"
directory="file://D:\check\error" delete-source-files="true"
/>
<si:channel id="checkFileErr" />
</beans>
my checkFlatPackCVSParserWrapper class is
public class checkFlatPackCVSParserWrapper {
private static final Log LOG = LogFactory.getLog("checkFlatPackCVSParserWrapper");
private Resource pzMapXML;
private char delimiter = ',';
private char qualifier = '"';
private boolean ignoreFirstRecord = false;
public Resource getPzMapXML() {
return pzMapXML;
}
public void setPzMapXML(Resource pzMapXML) {
this.pzMapXML = pzMapXML;
}
public char getDelimiter() {
return delimiter;
}
public void setDelimiter(char delimiter) {
this.delimiter = delimiter;
}
public char getQualifier() {
return qualifier;
}
public void setQualifier(char qualifier) {
this.qualifier = qualifier;
}
public boolean isIgnoreFirstRecord() {
return ignoreFirstRecord;
}
public void setIgnoreFirstRecord(boolean ignoreFirstRecord) {
this.ignoreFirstRecord = ignoreFirstRecord;
}
public Parser getParser(String csv) {
if(LOG.isDebugEnabled())
LOG.debug("getParser: " + csv);
Parser result = null;
try {
result = DefaultParserFactory.getInstance().newDelimitedParser(
pzMapXML.getInputStream(), //xml column mapping
new ByteArrayInputStream(csv.getBytes()), //txt file to parse
delimiter, //delimiter
qualifier, //text qualfier
ignoreFirstRecord);
}catch (Exception e) {
if(LOG.isDebugEnabled())
LOG.debug("Unable to read file: " + e );
throw new RuntimeException("File Parse exception");
}
return result;
}
}
sampleFileFormat.xml is
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE PZMAP SYSTEM "flatpack.dtd" >
<PZMAP>
<COLUMN name="FIRSTNAME" />
<COLUMN name="LASTNAME" />
</PZMAP>
and checkTransfomer is
public class checkTransfomer {
private static final Log LOG = LogFactory.getLog(checkTransfomer.class);
private CheckFlatPackCVSParserWrapper wrapper;
public String transform(String csv) {
Parser parser = wrapper.getParser(csv);
if(LOG.isDebugEnabled()) {
LOG.debug("Parser is: " + parser);
}
DataSet ds = parser.parse();
ArrayList<Check> list = new ArrayList<Check>();
while(ds.next()) {
Check check= new Check();
check.setFirstName(ds.getString("FIRSTNAME"));
check.setLastName(ds.getString("LASTNAME"));
if(LOG.isDebugEnabled()) {
LOG.debug("Bean value is: " + bean);
}
list.add(bean);
}
if(LOG.isDebugEnabled()) {
LOG.debug("Records fetched is: " + list.size());
}
return list.toString();
}
public CheckFlatPackCVSParserWrapper getWrapper() {
return wrapper;
}
public void setWrapper(CheckFlatPackCVSParserWrapper wrapper) {
this.wrapper = wrapper;
}
And my ErrorChannelWriter is
public class ErrorChannelWriter {
public static final Log LOG = LogFactory.getLog(ErrorChannelWriter.class);
public Message<?> transformError(ErrorMessage errorMessage) {
if (LOG.isDebugEnabled()) {
LOG.debug("Transforming errorMessage is: " + errorMessage);
}
return ((MessagingException) errorMessage.getPayload())
.getFailedMessage();
}
}
and my validagtion class is
com.check.Validation
public class Validation
{
void validation(CheckCheck)
{
if(Check.getFirstName().equals("maya"))
{
throw new RuntimeException("Name Already exist");
}
}
}
and my ListToStringTransfomer is
public class ListToStringTransfomer {
private static final Log LOG=LogFactory.getLog(ListToStringTransfomer.class);
public String transformList(List<IssueAppBean> list) {
return list.toString();
}
}
and my file containing one fields instead of two fields
> maya
here my file format is wrong, so record is moving to error folder.but there is no error message. how can i add error message(TOO FEW COLUMNS WANTED: 2 GOT: 1) when my file format is incorrect.
my requirement is in my error file should contaion
maya -TOO FEW COLUMNS WANTED: 2 GOT: 1 or(Any error message )
please give me any solution
I don't think that you should go through the error channel to solve this requirement. The main reason for this is that invalid input in this case is an expected scenario. The errorChannel is the channel that Spring Integration sends messages to if an unexpected exception happens in an endpoint.
If you add some header to the message if a validation failed, you can route based on that header and also record the failure message there. You can then send your error message to a log file or whatever on your own.

Resources