I am trying to use opencsv to parse a csv file like this:
name,purchase,date
TEST,TEST,2020-10-20T00:37:53.562000000Z
TEST,TEST,2020-10-20T00:37:53.562000000Z
I am trying to add the parsed data to a firebase database following this tutorial: https://attacomsian.com/blog/spring-boot-upload-parse-csv-file. This is my class for the data:
public class Records {
#CsvBindByName
private String name;
#CsvBindByName
private String purchase;
#CsvBindByName
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
When I parse the file I get this error:
Exception in thread "pool-6-thread-2" Exception in thread "pool-6-thread-1" Exception in thread "pool-6-thread-4" Exception in thread "pool-6-thread-3" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:99)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:128)
at com.opencsv.bean.BeanFieldSingleValue.convert(BeanFieldSingleValue.java:98)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:180)
at com.opencsv.bean.AbstractMappingStrategy.setFieldValue(AbstractMappingStrategy.java:581)
at com.opencsv.bean.AbstractMappingStrategy.populateNewBean(AbstractMappingStrategy.java:328)
at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:128)
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:83)
... 3 more
Caused by: org.apache.commons.beanutils.ConversionException: Can't convert value '2022-10-20T00:37:53.562000000Z' to type class com.google.cloud.Timestamp
at org.apache.commons.beanutils.converters.AbstractConverter.conversionException(AbstractConverter.java:474)
at org.apache.commons.beanutils.converters.StringConverter.convertToType(StringConverter.java:96)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:118)
... 9 more
How can i fix this error? Do I need to change the format of the date column? I copied the date format from a record in the database so that format is how it should be stored in the database
I changed the csv format to:
name,purchase,date
TEST,TEST,2018-09-16T08:00:00
TEST,TEST,2018-09-16T08:00:00
I modified the class that binds to the csv to look like this:
public class CsvRecords {
#CsvBindByName
private String name;
#CsvBindByName
private String purchase;
#CsvBindByName
private String date;
// get and setters left out for brevity pls comment if needed
}
The POJO class for the data in db:
public class Records {
private String name;
private String purchase;
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
When uploading in the controller class I then convert the string to LocalDateTime and then again to Timestamp like this:
#PostMapping("/upload-csv-file")
public String uploadCSVFile(#RequestParam("file") MultipartFile file, Model model) {
// validate file
if (file.isEmpty()) {
model.addAttribute("message", "Please select a CSV file to upload.");
model.addAttribute("status", false);
} else {
// parse CSV file to create a list of `User` objects
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
// create csv bean reader
CsvToBean<Records> csvToBean = new CsvToBeanBuilder(reader)
.withType(Records.class)
.withIgnoreLeadingWhiteSpace(true)
.build();
// convert `CsvToBean` object to list of records
List<Records> records = csvToBean.parse();
// save users in DB?
for(int i = 0; i<records.size(); i++){
LocalDateTime localDateTime = LocalDateTime.parse(records.get(i).getDate);
Timestamp timestamp = Timestamp.valueOf(localDateTime);
Records rec = new Records(records.get(i).getName(), records.get(i).getPurchase(), timestamp)
firebaseServices.saveDetails(rec);
}
} catch (Exception ex) {
model.addAttribute("message", "An error occurred while processing the CSV file.");
model.addAttribute("status", false);
}
}
return "file-upload-status";
}
For details on the implementation of the firebaseServices class (saveDetails method) I used this tutorial
Could you have a try in this case that replaces the Timestamp to Date?
like follow this:
#CsvBindByName private Date date;
The timestamp field object is an instance from com.google.cloud.Timestamp package.
As #Allen suggested, you might have to look into java.util.date or event better, the Java 8 time APIs java.time.LocalTime to get support from ConverterPrimitiveTypes to be converted automatically.
Related
I tried to rebuild the sample from the XDocReport documentation, but when i try to create tables or fill them. It always fails due to the follwing error. I cannot figure out what the issue is...
I have updated all the dependencies and tried different syntax in the .odt file.
ERROR:
Apr. 12, 2022 10:21:05 VORM. freemarker.log._JULLoggerFactory$JULLogger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
The following has evaluated to null or missing:
==> devs.name [in template "fr.opensagres.xdocreport.document.odt.ODTReport#57855c9a!content.xml" at line 5, column 11]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use [#if myOptionalVar??]when-present[#else]when-missing[/#if]. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: ${devs.name} auto-escaped [in template "fr.opensagres.xdocreport.document.odt.ODTReport#57855c9a!content.xml" at line 5, column 9]
----
Java stack trace (for programmers):
----
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481)
at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401)
at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370)
at freemarker.core.BuiltInForLegacyEscaping._eval(BuiltInForLegacyEscaping.java:34)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.MethodCall._eval(MethodCall.java:55)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.MethodCall._eval(MethodCall.java:55)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.MethodCall._eval(MethodCall.java:55)
at freemarker.core.Expression.eval(Expression.java:101)
at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
at freemarker.core.Environment.visit(Environment.java:383)
at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321)
at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271)
at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244)
at freemarker.core.Environment.visitIteratorBlock(Environment.java:657)
at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108)
at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94)
at freemarker.core.Environment.visit(Environment.java:347)
at freemarker.core.Environment.visit(Environment.java:353)
at freemarker.core.Environment.visit(Environment.java:353)
at freemarker.core.Environment.process(Environment.java:326)
at fr.opensagres.xdocreport.template.freemarker.FreemarkerTemplateEngine.process(FreemarkerTemplateEngine.java:163)
at fr.opensagres.xdocreport.template.freemarker.FreemarkerTemplateEngine.processNoCache(FreemarkerTemplateEngine.java:122)
at fr.opensagres.xdocreport.template.AbstractTemplateEngine.process(AbstractTemplateEngine.java:118)
at fr.opensagres.xdocreport.template.AbstractTemplateEngine.process(AbstractTemplateEngine.java:83)
at fr.opensagres.xdocreport.document.AbstractXDocReport.processTemplateEngine(AbstractXDocReport.java:772)
at fr.opensagres.xdocreport.document.AbstractXDocReport.process(AbstractXDocReport.java:518)
at fr.opensagres.xdocreport.document.AbstractXDocReport.process(AbstractXDocReport.java:484)
at report_creation.fillList.main(fillList.java:51)
I am currently using this code:
fillList.java
public class fillList {
public static void main(String[] args) {
try {
// 1) Load ODT file by filling Velocity template engine and cache
// it to the registry
InputStream in = fillList.class.getResourceAsStream("Test.odt");
IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
// 2) Create fields metadata to manage lazy loop (#foreach velocity)
// for table row.
FieldsMetadata metadata = new FieldsMetadata();
metadata.addFieldAsList("developers.name");
metadata.addFieldAsList("developers.lastName");
metadata.addFieldAsList("developers.mail");
report.setFieldsMetadata(metadata);
// 3) Create context Java model
IContext context = report.createContext();
Project project = new Project("Create Dynamic Reports", 101);
context.put("project", project);
// Register developers list
List<Developer> developers = new ArrayList<>();
developers.add(new Developer("ZERR", "Angelo", "angelo.zerr#gmail.com"));
developers.add(new Developer("Leclercq", "Pascal", "pascal.leclercq#gmail.com"));
context.put("developers", developers);
// 4) Generate report by merging Java model with the ODT
OutputStream out = new FileOutputStream(new File("Test2_out.odt"));
report.process(context, out);
System.out.println("Report creation successfully completed!");
} catch (IOException e) {
System.err.println("[Debug Assistent]: No report created! >> IOException");
e.printStackTrace();
} catch (XDocReportException e) {
System.err.println("[Debug Assistent]: No report created! >> XDocReportException");
e.printStackTrace();
}
}
}
Project.java
public class Project {
private final String name;
private final Integer ID;
public Project(String name, Integer id) {
this.name = name;
this.ID = id;
}
public String getName() {
return name;
}
public Integer getID() {
return ID;
}
}
Developer.java
public class Developer {
private final String name;
private final String lastName;
private final String mail;
public Developer(String name, String lastName, String mail) {
this.name = name;
this.lastName = lastName;
this.mail = mail;
}
public String getFirstName() {
return name;
}
public String getLastName() {
return lastName;
}
public String getMail() {
return mail;
}
}
This is the .odt file i am using.
In the Developer class you have getFirstName instead of getName. Hence dev.name won't work.
Im using Univocity CSV parser with routines when I iterate over Java beans. Is there a way to validate CSV header? When I edit the CSV and add invalid header, it just insert into given bean null without any error.
Model class:
public class Customer {
#Format(formats ="yyyy-MM-dd")
#Parsed(field="C_DAY")
private Date day;
#Parsed(field="C_ID")
private Long id;
#Parsed(field="C_TYPE")
private String type;
#Format(formats ="yyyy-MM-dd")
#Parsed(field="C_ORIGIN_DATE")
private Date originDate;
#Format(formats ="yyyy-MM-dd")
#Parsed(field="C_REL_DATE")
private Date relDate;
#Parsed(field="C_LEGAL_ID")
private String legalId;
#Parsed(field="C_NAME")
private String name;}
Parser:
#Autowired
private CustomerDAO dao;
public void parse(File file) throws IOException, SQLException, CustomerValidationException, ParseException {
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.getFormat().setLineSeparator("\n");
parserSettings.setHeaderExtractionEnabled(false);
CsvRoutines routines = new CsvRoutines(parserSettings);
List<Customer> customers = new ArrayList<>();
java.util.Date stamp = getTimestamp(file);
dao.checkTimestampDate(stamp);
for (Customer customer : routines.iterate(Customer.class, file, "UTF-8")) {
validateFileDateWithFileName(stamp, customer.getDay());
validateCustomer(customer);
customers.add(customer);
}
dao.save(customers);
}
Author of the library here. The BeanListProcessor has a strictHeaderValidationEnabled property you can set to true to ensure all headers in your class exist in the input.
You just can't use the CsvRoutines in that case as that class implements convenience methods that use their own internal row processors, so yours will be ignored. Try this code:
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.getFormat().setLineSeparator("\n");
final List<Customer> customers = new ArrayList<>();
final java.util.Date stamp = getTimestamp(file);
dao.checkTimestampDate(stamp);
parserSettings.setProcessor(new BeanProcessor<Customer>() {
#Override
public void beanProcessed(Customer customer, ParsingContext context) {
validateFileDateWithFileName(stamp, customer.getDay());
validateCustomer(customer);
customers.add(customer);
}
});
new CsvParser(parserSettings).parse(file, "UTF-8");
dao.save(customers);
Hope this helps.
Based on answer by Jeronimo Backes.
In case you have #Header annotation on the bean or know the exact headers but still need setHeaderExtractionEnabled(true):
public <T> List<T> parse(File file, Class<T> beanType, char delimiter, Charset charset) {
String[] headers = beanType.getDeclaredAnnotation(Headers.class).sequence(); // or other source
CsvParserSettings parserSettings = Csv.parseRfc4180(); // or some other
parserSettings.detectFormatAutomatically(delimiter);
parserSettings.setHeaderExtractionEnabled(true);
// initialize new processor (stateful, should not be reused! See implementation of parseAll)
BeanListProcessor<T> processor= new BeanListProcessor<>();
processor.setStrictHeaderValidationEnabled(true);
parserSettings.setProcessor(processor);
CsvParser csvParser = new CsvParser(parserSettings);
csvParser.parse(file, charset);
// header validation
String[] headersParsed = processor.getHeaders();
if (!Arrays.equals(headers, headersParsed)) {
String message = String.format("Header validation failed. Expected: %s, but was: %s",
Arrays.toString(headers), Arrays.toString(headersParsed));
throw new DataProcessingException(message);
}
return beanListProcessor.getBeans();
}
I'm using openCsv library cause it's very easy to use and I got all necessary functional. But now I need to use some custom logic except checking for correct types, columns and other usual things. I have a csv with columns firstName, secondName, firstSalary, lastSalary and others. I want to check that firstDayOfWork is less than lastDayOfWork in the process of parcing and add a new csvException if it is false. So, if now I'm parcing file
firstName,secondName,firstSalary,lastSalary
John, Doe, testtext, 5000
Alice, , 100, 5000
Harry, Smith, 400, 200
and processing a list of csvExcpetions I can get results of parcing like
Number of mistakes: 2
Line 1: Conversion of testtext to java.lang.Integer failed.
Line 2: Field 'secondName' is mandatory but no value was provided.
I want to something like
Number of mistakes: 3
Line 1: Conversion of testtext to java.lang.Integer failed.
Line 2: Field 'secondName' is mandatory but no value was provided.
Line 3: firstSalary cannot be more than lastSalary
Or some custom parcing logic like check if some field catch regexp, two fields at the same time greater than 0, etc.
I can firstly parce and convert it to beans and by the second cycle check my beans to these rules, but there are can be a lot of lines and it will take longer, so, I want to check it in the one process.
Can I get it by openCsv? And if yes, how? If no, what another tool I can use?
Thank you.
based on How to create a list of valid CSV records by logging the error of invalid record using OpenCsv?, instead of throwing an IllegalArgumentException in the setters, you could:
create a BeanVerifier to verify the whole bean after creation;
throw a CsvConstraintViolationException on error;
add .withThrowExceptions(false) to the CsvToBeanBuilder;
Invoke getCapturedExceptions() to collect the validation errors.
The advantage of this solution is that you can collect the list of CSV exceptions as you wanted:
Example
final CsvToBean<EmployeeBean> csvToBean =
new CsvToBeanBuilder<EmployeeBean>(new FileReader("c:\\test.csv"))
.withType(EmployeeBean.class)
.withVerifier(new EmployeeSalaryVerifier())
.withThrowExceptions(false)
.build();
final List<EmployeeBeans> employees = csvToBean.parse();
List<CsvException> exceptions = parser.getCapturedExceptions();
// logging number of mistakes and, for each exception, its line number and message
logger.error("Number of Mistakes: {}", exceptions.size());
employees.getCapturedExceptions().stream().forEach(ex ->
logger.error("Line {}: {}", ex.getLineNumber(), ex.getMessage(), ex));
EmployeeBean
public class EmployeeBean {
#CsvBindByName(column = "First Name", required = true)
private String firstName;
#CsvBindByName(column = "Last Name", required = true)
private String lastName;
#CsvBindByName(column = "First Salary" required = true)
private Long firstSalary;
#CsvBindByName(column = "Last Salary")
private Long lastSalary;
// regular getters and setters, no validation here
}
BeanVerifier
public class EmployeeSalaryVerifier implements BeanVerifier<EmployeeBean> {
#Override
public boolean verifyBean(Employee bean) throws CsvConstraintViolationException {
// check salary
if (bean.getLastSalary() != null && bean.getFirstSalary().compareTo(bean.getLastSalary()) > 0) {
throw new CsvConstraintViolationException("First Salary cannot be greater than Last Salary.");
}
return true;
}
While there is a request on the todo/wish list for OpenCSV I don't think it will help you because it's about pre parsing validation
For what you want you should just add a check in your setters to throw an exception when the values are bad. Here is my Bean and test.
public class SetterBean {
#CsvBindByName(column = "First Name", required = true)
private String firstName;
#CsvBindByName(column = "Last Name", required = true)
private String lastName;
#CsvBindByName(column = "First Salary")
private Long firstSalary;
#CsvBindByName(column = "Last Salary")
private Long lastSalary;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setFirstSalary(Long firstSalary) {
if (lastSalary != null && (firstSalary.compareTo(lastSalary) > 0)) {
throw new IllegalArgumentException("First Salary cannot be greater than Last Salary.");
}
this.firstSalary = firstSalary;
}
public void setLastSalary(Long lastSalary) {
if (firstSalary != null && (lastSalary.compareTo(firstSalary) < 0)) {
throw new IllegalArgumentException("Last Salary cannot be less than First Salary.");
}
this.lastSalary = lastSalary;
}
}
public class SetterValidationTest {
private static final String HEADER = "First Name,Last Name,First Salary,Last Salary\n";
CsvToBean<SetterBean> csvToBean;
#Test
public void normalData() {
String data = HEADER + "First, Last, 1, 2";
csvToBean = new CsvToBeanBuilder<SetterBean>(new StringReader(data))
.withType(SetterBean.class)
.build();
List<SetterBean> beans = csvToBean.parse();
assertEquals(1, beans.size());
}
#Test(expected = Exception.class)
public void firstGTLast() {
String data = HEADER + "First, Last, 2, 1";
csvToBean = new CsvToBeanBuilder<SetterBean>(new StringReader(data))
.withType(SetterBean.class)
.build();
List<SetterBean> beans = csvToBean.parse();
}
}
And here is the result.
Exception in thread "pool-1-thread-1" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException
at com.opencsv.bean.AbstractBeanField.assignValueToField(AbstractBeanField.java:192)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:159)
at com.opencsv.bean.concurrent.ProcessCsvLine.processField(ProcessCsvLine.java:140)
at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:126)
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:82)
... 3 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.opencsv.bean.AbstractBeanField.assignValueToField(AbstractBeanField.java:187)
... 7 more
Caused by: java.lang.IllegalArgumentException: Last Salary cannot be less than First Salary.
at integrationTest.BeanTests.SetterBean.setLastSalary(SetterBean.java:33)
... 12 more
Hope that helps.
Scott Conway :)
I'm using the SolrJ client to call the Solr service, is there any way to modify the response that I got from Solr like adding a new field in the response docs.
QueryResponse rsp = null;
if (server != null) {
try {
rsp = server.query(solrParams);
} catch (Exception e) {
e.getMessage();
}
}
If my response is something like below
{
"responseHeader":{
"status":400,
"QTime":15,
"params":{
"q":"*:*",
"indent":"true",
"wt":"json",
"group":"false"}},
"response":{"numFound":1,"start":0,"docs":[
{
"Name":"Shirt",
"inventory":"Nonn",
"launchYear":2004,
"Desc":"Men's Shirt",
"ilnNumbers":"25326,25338,25341,29617,39267",}
}}
I need to change this response to add a new field
{
"responseHeader":{
"status":400,
"QTime":15,
"params":{
"q":"*:*",
"indent":"true",
"wt":"json",
"group":"false"}},
"response":{"numFound":1,"start":0,"docs":[
{
"Name":"Shirt",
"inventory":"Nonn",
"launchYear":2004,
"myCustomField":"Test",
"Desc":"Men's Shirt",
"ilnNumbers":"25326,25338,25341,29617,39267",}
}}
Is this possible?
Define a POJO class for your schema along with getters and setters.
class POJO {
#Field
private String name;
#Field
private Integer inventory;
#Field
private Integer launchYear;
#Field
private String desc;
#Field
private String ilnNumbersl;
private String myCustomField;
public POJO(String name, Integer inventory, Integer launchYear, String desc, String ilnNumbersl) {
this.name = name;
this.inventory = inventory;
this.launchYear = launchYear;
this.desc = desc;
this.ilnNumbersl = ilnNumbersl;
}
//getters and setters for each instance member.
}
Now convert the solr response into List and add the required custom field to the each result returned by the query.
QueryResponse rsp = null;
if (server != null) {
try {
rsp = server.query(solrParams);
List<POJO> list = rsp.getBeans(POJO.class); // convert to list of POJO instance
// now add the custom field for each
} catch (Exception e) {
e.getMessage();
}
}
Try JsonResponceWriter from Solr Documentation.This will help you solve your problem.
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
<!-- For the purposes of the tutorial, JSON response are written as
plain text so that it's easy to read in *any* browser.
If you are building applications that consume JSON, just remove
this override to get the default "application/json" mime type.
-->
<str name="content-type">text/plain</str>
</queryResponseWriter>
This will give you queryResponce in Text format. Modify That responce according to your use.
I am facing this issue(getting null response) when i am trying to Query in Java using
I need to based on placed time stamp range and releases desc and status.
// My document as follows:
<ordersAuditRequest>
<ordersAudit>
<createTS>2013-04-19 12:19:17.165</createTS>
<orderSnapshot>
<orderId>43060151</orderId>
<placedTS>2013-04-19 12:19:17.165</placedTS>
<releases>
<ffmCenterDesc>TW</ffmCenterDesc>
<relStatus>d </relStatus>
</releases>
</ordersAudit>
</ordersAuditRequest>
I am using following query but it returns null.
Query query = new Query();
query.addCriteria(Criteria.where("orderSnapshot.releases.ffmCenterDesc").is(ffmCenterDesc)
.and("orderSnapshot.releases.relStatus").is(relStatus)
.andOperator(
Criteria.where("orderSnapshot.placedTS").gt(orderPlacedStart),
Criteria.where("orderSnapshot.placedTS").lt(orderPlacedEnd)
)
);
I can't reproduce your problem, which suggests that the issue is with the values in the database and the values you're passing in to the query (i.e. they're not matching). This is not unusual when you're trying to match dates, as you need to make sure they're stored as ISODates in the database and queried using java.util.date in the query.
I have a test that shows your query working, but I've made a number of assumptions about your data.
My test looks like this, hopefully this will help point you in the correct direction, or if you give me more feedback I can re-create your problem more accurately.
#Test
public void shouldBeAbleToQuerySpringDataWithDates() throws Exception {
// Setup - insert test data into the DB
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd' 'hh:mm:ss.SSS");
MongoTemplate mongoTemplate = new MongoTemplate(new Mongo(), "TheDatabase");
// cleanup old test data
mongoTemplate.getCollection("ordersAudit").drop();
Release release = new Release("TW", "d");
OrderSnapshot orderSnapshot = new OrderSnapshot(43060151, dateFormat.parse("2013-04-19 12:19:17.165"), release);
OrdersAudit ordersAudit = new OrdersAudit(dateFormat.parse("2013-04-19 12:19:17.165"), orderSnapshot);
mongoTemplate.save(ordersAudit);
// Create and run the query
Date from = dateFormat.parse("2013-04-01 01:00:05.000");
Date to = dateFormat.parse("2014-04-01 01:00:05.000");
Query query = new Query();
query.addCriteria(Criteria.where("orderSnapshot.releases.ffmCenterDesc").is("TW")
.and("orderSnapshot.releases.relStatus").is("d")
.andOperator(
Criteria.where("orderSnapshot.placedTS").gt(from),
Criteria.where("orderSnapshot.placedTS").lt(to)
)
);
// Check the results
List<OrdersAudit> results = mongoTemplate.find(query, OrdersAudit.class);
Assert.assertEquals(1, results.size());
}
public class OrdersAudit {
private Date createdTS;
private OrderSnapshot orderSnapshot;
public OrdersAudit(final Date createdTS, final OrderSnapshot orderSnapshot) {
this.createdTS = createdTS;
this.orderSnapshot = orderSnapshot;
}
}
public class OrderSnapshot {
private long orderId;
private Date placedTS;
private Release releases;
public OrderSnapshot(final long orderId, final Date placedTS, final Release releases) {
this.orderId = orderId;
this.placedTS = placedTS;
this.releases = releases;
}
}
public class Release {
String ffmCenterDesc;
String relStatus;
public Release(final String ffmCenterDesc, final String relStatus) {
this.ffmCenterDesc = ffmCenterDesc;
this.relStatus = relStatus;
}
}
Notes:
This is a TestNG class, not JUnit.
I've used SimpleDateFormat to create Java Date classes, this is just for ease of use.
The XML value you pasted for relStatus included spaces, which I have stripped.
You showed us the document structure in XML, not JSON, so I've had to assume what your data looks like. I've translated it almost directly into JSON, so it looks like this in the database:
{
"_id" : ObjectId("51d689843004ec60b17f50de"),
"_class" : "OrdersAudit",
"createdTS" : ISODate("2013-04-18T23:19:17.165Z"),
"orderSnapshot" : {
"orderId" : NumberLong(43060151),
"placedTS" : ISODate("2013-04-18T23:19:17.165Z"),
"releases" : {
"ffmCenterDesc" : "TW",
"relStatus" : "d"
}
}
}
You can find what yours really looks like by doing a db.<collectionName>.findOne() call in the mongoDB shell.