How to handle null pointer exceptions in elasticsearch - nullpointerexception

I'm using elasticsearch and i was trying to handle the case when the database is empty
#SuppressWarnings("unchecked")
public <M extends Model> SearchResults<M> findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
BoolQueryBuilder qb = buildQueryBuilder(search, searchFields, where);
Query<M> query = (Query<M>) ElasticSearch.query(qb, entityClass);
// FIXME Currently we ignore the orderBy and order fields
query.from((page - 1) * getPageSize()).size(getPageSize());
query.hydrate(true);
return query.fetch();
}
the error at return query.fetch();
i'm trying to implement a try and catch statement but it's not working, any one can help with this please?

Related

ArrayIndexOutOfBounds exception for an empty string on #RestQuery

I have a handler in my rest easy lamda application
with the url: http://localhost:8080/store/search/v1/suggest
public List<Map<String, Object>> storeSearch(
#RestHeader("id") String id,
#RestQuery final String q,
#RestQuery final String columns) {
if (StringUtils.isBlank(q)) {
logger.error("Search query is empty");
return Collections.EMPTY_LIST;
}
The app is doing well for below cases but failing if q is empty
http://localhost:8080/store/search/v1/suggest?q=ab
http://localhost:8080/store/search/v1/suggest
failing here
http://localhost:8080/store/search/v1/suggest?q=
Can you please suggest me what I am missing here.

Can't get search for modification time to work

The example in package org.apache.lucene.demo works for text search.
But I can't get it to work using and displaying modification time.
It seems that the field modified is handled but no success using it.
Running SearchFiles prints hits for
Enter query:
+kompl*
but nothing here
+kompl* +modified:[0 TO 9999999999999]
Can someone provide an example for this?
I had the wrong assumption that file attributes are somehow implicitly available to me.
But ok, I had to do it by myself.
For indexing I added a simple integer
// provide stored date integer to query for [yyyymmdd]
Date dt = new Date(lastModified);
int myDays = (dt.getYear()+1900)*100*100 + (dt.getMonth()+1)*100 + dt.getDate();
doc.add(new IntPoint("moddate", myDays ));
doc.add(new StoredField("moddateVal", myDays ));
For searching I handle this field by an extended parser
public static class QueryParserModdate extends QueryParser {
public QueryParserModdate(String f, Analyzer a) {
super(f, a);
}
protected Query getRangeQuery(String field, String part1, String part2,
boolean startInclusive, boolean endInclusive)
throws ParseException {
if (field.equalsIgnoreCase("moddate")) {
int part1Int = Integer.MIN_VALUE;
int part2Int = Integer.MAX_VALUE;
try {
part1Int = Integer.parseInt(part1);
} catch (Exception e) {
...
Query query = IntPoint.newRangeQuery("moddate", part1Int,
part2Int);
return query;
}
return super.getRangeQuery(field, part1, part2, startInclusive,
endInclusive);
}
For sure not beautiful but working for me.

jdbcTemplate query row map date column generically

I have a database with a date column, and when I perform a query I get each row as a Map of column names to column values. My problem is I do not know how to generically get the date column.
I am simply trying to cast it to a String at the moment, then parse it as java.util.Date, but this errors at the cast, and I am otherwise unsure as to how I can get the data?
This code is supposed to work with Sybase and Oracle databases too, so a generic answer would be greatly appreciated!
private static final String USER_QUERY = "SELECT USERNAME, PASSWORD, SUSPEND_START_DATE, SUSPEND_END_DATE FROM USERS";
public User readUsers(Subjects subjects) throws SubjectReaderException {
/* Perform the query */
List<User> users = new ArrayList<User>();
List<Map<String, Object>> rows = jdbcTemplate.queryForList(USER_QUERY);
/* Map the returned rows to our User objects */
for (Map<String, Object> row : rows) {
String username = (String) row.get("USERNAME");
/* Check if the user is suspended */
if(checkUserIsSuspended(row)){
continue;
}
User user = new User();
user.setUsername(username);
user.setPassword((String) row.get("PASSWORD"));
users.add(user);
}
return users;
}
private boolean checkUserIsSuspended(Map<String, Object> row) throws SubjectReaderException {
final String startDateString = (String) row.get("SUSPEND_START_DATE"); // this errors
if (startDateString != null) {
final String endDateString = (String) row.get("SUSPEND_END_DATE");
if (null != endDateString) {
return checkDate(startDateString, endDateString); // this just compares the current date etc
}
/* Return true if the Suspended start date is not null, and there is no end date column, or it is null */
return true;
}
/* Return false if the Suspended start date String is null - i.e. they have not been suspended */
return false;
}
The error:
java.lang.ClassCastException: com.sybase.jdbc3.tds.SybTimestamp cannot be cast to java.lang.String
It will always give this error because you are casting the Object com.sybase.jdbc3.tds.SybTimestamp to String.
Why don't you make this check directly in the SQL instead of creating a filter? Something like
SELECT USERNAME, PASSWORD, SUSPEND_START_DATE, SUSPEND_END_DATE
FROM USERS WHERE SUSPEND_START_DATE >= ?
and now you can use the queryForList passing as parameter the current time.
Another way for you to avoid this direct casts is using RowMapper. This way you can use ResultSet#getDate(String) and you won't be needing to cast anything as the JDBC driver will take care of the conversion for you :)

Does Dapper support the like operator?

Using Dapper-dot-net...
The following yields no results in the data object:
var data = conn.Query(#"
select top 25
Term as Label,
Type,
ID
from SearchTerms
WHERE Term like '%#T%'",
new { T = (string)term });
However, when I just use a regular String Format like:
string QueryString = String.Format("select top 25 Term as Label, Type, ID from SearchTerms WHERE Term like '%{0}%'", term);
var data = conn.Query(QueryString);
I get 25 rows back in the collection. Is Dapper not correctly parsing the end of the parameter #T?
Try:
term = "whateverterm";
var encodeForLike = term => term.Replace("[", "[[]").Replace("%", "[%]");
string term = "%" + encodeForLike(term) + "%";
var data = conn.Query(#"
select top 25
Term as Label,
Type,
ID
from SearchTerms
WHERE Term like #term",
new { term });
There is nothing special about like operators, you never want your params inside string literals, they will not work, instead they will be interpreted as a string.
note
The hard-coded example in your second snippet is strongly discouraged, besides being a huge problem with sql injection, it can cause dapper to leak.
caveat
Any like match that is leading with a wildcard is not SARGable, which means it is slow and will require an index scan.
Yes it does. This simple solution has worked for me everytime:
db.Query<Remitente>("SELECT *
FROM Remitentes
WHERE Nombre LIKE #n", new { n = "%" + nombre + "%" })
.ToList();
Best way to use this to add concat function in query as it save in sql injecting as well, but concat function is only support above than sql 2012
string query = "SELECT * from country WHERE Name LIKE CONCAT('%',#name,'%');"
var results = connection.query<country>(query, new {name});
The answer from Sam wasn't working for me so after some testing I came up with using the SQLite CONCAT equivalent which seems to work:
string sql = "SELECT * FROM myTable WHERE Name LIKE '%' || #NAME || '%'";
var data = IEnumerable data = conn.Query(sql, new { NAME = Name });
Just to digress on Sam's answer, here is how I created two helper methods to make searches a bit easier using the LIKE operator.
First, creating a method for generating a parameterized query, this method uses dynamic: , but creating a strongly typed generic method should be more desired in many cases where you want static typing instead of dynamic.
public static dynamic ParameterizedQuery(this IDbConnection connection, string sql, Dictionary<string, object> parametersDictionary)
{
if (string.IsNullOrEmpty(sql))
{
return null;
}
string missingParameters = string.Empty;
foreach (var item in parametersDictionary)
{
if (!sql.Contains(item.Key))
{
missingParameters += $"Missing parameter: {item.Key}";
}
}
if (!string.IsNullOrEmpty(missingParameters))
{
throw new ArgumentException($"Parameterized query failed. {missingParameters}");
}
var parameters = new DynamicParameters(parametersDictionary);
return connection.Query(sql, parameters);
}
Then adding a method to create a Like search term that will work with Dapper.
public static string Like(string searchTerm)
{
if (string.IsNullOrEmpty(searchTerm))
{
return null;
}
Func<string, string> encodeForLike = searchTerm => searchTerm.Replace("[", "[[]").Replace("%", "[%]");
return $"%{encodeForLike(searchTerm)}%";
}
Example usage:
var sql = $"select * from products where ProductName like #ProdName";
var herringsInNorthwindDb = connection.ParameterizedQuery(sql, new Dictionary<string, object> { { "#ProdName", Like("sild") } });
foreach (var herring in herringsInNorthwindDb)
{
Console.WriteLine($"{herring.ProductName}");
}
And we get our sample data from Northwind DB:
I like this approach, since we get helper extension methods to do repetitive work.
My solution simple to this problem :
parameter.Add("#nomeCliente", dfNomeCliPesquisa.Text.ToUpper());
query = "SELECT * FROM cadastrocliente WHERE upper(nome) LIKE " + "'%" + dfNomeCliPesquisa.Text.ToUpper() + "%'";

NHibernate: Add criteria if param not null

I'm trying to retrieve a list of orders based on parameters specified by a user (basic search functionality). The user will enter either an orderId or a bunch of other params, those will get wrapped up into a message, and eventually make their way to the method below. My question is, how do I only look at the parameters that actually have values? So if a user were to enter a received date range and a store number and all other fields were null, I want to return orders for stores received in the date range and ignore all the null parameters. At first I was thinking I could use a conjunction, but I can't see a way to ignore the null parameters. Then I started splitting things out into the if statements below the main expression, but I don't want to look at those criteria if the user provides an externalId. Is there a simple way to do this?
public IList<Core.Order> GetOrderByCriteria
(
string ExternalId,
int? Store,
int? Status,
DateTime? beforeTransmissionDate, DateTime? afterTransmissionDate,
DateTime? beforeAllocationProcessDate, DateTime? afterAllocationProcessDate,
DateTime? beforeReceivedDate, DateTime? afterReceivedDate
)
{
try
{
NHibernate.ICriteria criteria = NHibernateSession.CreateCriteria(typeof(Core.Order))
.Add(Expression.Or
(
Expression.Like("ExternalId", ExternalId),
Expression.Conjunction()
.Add(Expression.Between("ReceivedDate", beforeReceivedDate, afterReceivedDate))
.Add(Expression.Between("TransmissionDate", beforeTransmissionDate, afterTransmissionDate))
.Add(Expression.Between("AllocationProcessDate", beforeAllocationProcessDate, afterAllocationProcessDate))
)
);
if(Store.HasValue)
criteria.Add(Expression.Eq("Status", Status));
if(Status.HasValue)
criteria.Add(Expression.Eq("Store", Store));
return criteria.List<Core.Order>();
}
catch (NHibernate.HibernateException he)
{
DataAccessException dae = new DataAccessException("NHibernate Exception", he);
throw dae;
}
}
I wound up dropping the whole conjunction thing and replacing the code in the try block with the code below. I also used joins which reduced the number of db accesses and reduced the amount of code needed.
NHibernate.ICriteria criteria = NHibernateSession.CreateCriteria(typeof(Core.Order));
if (!String.IsNullOrEmpty(ExternalId))
{
criteria.Add(Expression.Like("ExternalId", ExternalId));
}
if (beforeReceivedDate != null && afterReceivedDate != null)
criteria.Add(Expression.Between("ReceivedDate", beforeReceivedDate, afterReceivedDate));
if (beforeTransmissionDate != null && afterTransmissionDate != null)
criteria.Add(Expression.Between("TransmissionDate", beforeTransmissionDate, afterTransmissionDate));
if (beforeAllocationProcessDate != null && afterAllocationProcessDate != null)
criteria.Add(Expression.Between("AllocationProcessDate", beforeAllocationProcessDate, afterAllocationProcessDate));
if (Store.HasValue)
criteria.CreateCriteria("Store", "Store").Add(Expression.Eq("Store.LocationNumber", Store.Value));
return criteria.List<Core.Order>();
I had to do something similar not long ago. I'm pretty sure you can modify this to fit your needs.
private ICriteria AddSearchCriteria(ICriteria criteria, string fieldName, string value)
{
if (string.IsNullOrEmpty(fieldName))
return criteria;
if(string.IsNullOrEmpty(value))
return criteria;
criteria.Add(Expression.Like(fieldName, "%" + value + "%"));
return criteria;
}
The code calling the method ended up looking like this:
var query = session.CreateCriteria(typeof (User));
AddSearchCriteria(query, "FirstName", form["FirstName"]);
AddSearchCriteria(query, "LastName", form["LastName"]);
var resultList = new List<User>();
query.List(resultList);
return resultList;
Leave it up to the function to determine if the input is valid and whether to return the unmodified ICriteria or to add another Expression before returning it.