In ActiveJDBC how to update value of one of the Composite Key fields? - activejdbc

I am using ActiveJDBC. I have a table that is made up of a composite key (parentId, childId, effStartDate). I have a new requirement to allow the updating of the effStartDate field. When I tried to update the field and save, it errors out. Is there an appropriate way to update this using the ORM or a raw SQL approach in ActiveJDBC?
Current approach:
mymodel.setEffStartDate(newStartDate);
mymodel.saveIt();
Updated to provide more details. Here's the exact code:
try {
ri.setEffStartDate(ld);
boolean didItSave = ri.saveIt(user);
System.out.println("here - " + didItSave);
} catch(Exception e) {
System.out.println("Exception: " + e);
}
When the saveIt runs, it doesn't error out. However, it returns FALSE and nothing gets updated in the database. So I misused "errors" in my earlier statement. I should have said it just doesn't do anything.
We are using Oracle database.
The model class trying to update:
package com.brookdale.model;
import java.time.LocalDate;
import org.javalite.activejdbc.annotations.BelongsTo;
import org.javalite.activejdbc.annotations.BelongsToParents;
import org.javalite.activejdbc.annotations.CompositePK;
import org.javalite.activejdbc.annotations.Table;
import org.javalite.activejdbc.validation.ValidationException;
import com.brookdale.model.activejdbc.CecilModel;
#Table("MONET.CONTACTREL")
#CompositePK({ "parentContactID", "childContactID", "contactRelTypeID", "effStartDate" })
#BelongsToParents({
#BelongsTo(foreignKeyName="relationshipId",parent=Relationship.class),
#BelongsTo(foreignKeyName="contactRelTypeID",parent=ContactRelType.class),
// #BelongsTo(foreignKeyName="parentContactID",parent=Contact.class),
// #BelongsTo(foreignKeyName="childContactID",parent=Contact.class),
#BelongsTo(foreignKeyName="childContactID",parent=Contact.class),
#BelongsTo(foreignKeyName="childContactID",parent=ResidentContactDetail.class)
})
public class ContactRel extends CecilModel {
private ResidentContactDetail emergResidentContactDetail;
private ResidentContactDetail healthResidentContactDetail;
private ResidentContactDetail finResidentContactDetail;
private int emergresidentind = 0;
public Long getParentContactID() {
return getLong("parentContactID");
}
public void setParentContactID(Long parentContactID) {
set("parentContactID",parentContactID);
}
public Long getChildContactID() {
return getLong("childContactID");
}
public void setChildContactID(Long childContactID) {
set("childContactID",childContactID);
}
public LocalDate getEffStartDate() {
return getLocalDate("effStartDate");
}
public void setEffStartDate(LocalDate effStartDate) {
setLocalDate("effStartDate",effStartDate);
}
public LocalDate getEffEndDate() {
return getLocalDate("effEndDate");
}
public void setEffEndDate(LocalDate effEndDate) {
setLocalDate("effEndDate",effEndDate);
}
public Integer getContactRelTypeID() {
return getInteger("contactRelTypeID");
}
public void setContactRelTypeID(Integer contactRelTypeID) {
set("contactRelTypeID",contactRelTypeID);
}
public Integer getRelationshipId() {
return getInteger("relationshipId");
}
public void setRelationshipId(Integer relationshipId) {
set("relationshipId",relationshipId);
}
public Integer getParentIsPrimaryResidentInd() {
return getInteger("parentIsPrimaryResidentInd");
}
public void setParentIsPrimaryResidentInd(Integer parentIsPrimaryResidentInd) {
set("parentIsPrimaryResidentInd",parentIsPrimaryResidentInd);
}
public Integer getParentIsSecondPersonInd() {
return getInteger("parentIsSecondPersonInd");
}
public void setParentIsSecondPersonInd(Integer parentIsSecondPersonInd) {
set("parentIsSecondPersonInd",parentIsSecondPersonInd);
}
public int getCourtesyCopyInd() {
return getInteger("courtesyCopyInd");
}
public void setCourtesyCopyInd(Integer courtesyCopyInd) {
set("courtesyCopyInd",courtesyCopyInd);
}
/* Additional helper methods */
public Contact getParentContact() {
return Contact.findById(getParentContactID());
}
public Contact getChildContact() {
return Contact.findById(getChildContactID());
}
public int getEmergresidentind() {
return emergresidentind;
}
public void setEmergresidentind(int emergresidentind) {
this.emergresidentind = emergresidentind;
}
#Override
public void validate(){
super.validate();
validatePresenceOf("parentContactID", "Parent Contact is required.");
validatePresenceOf("childContactID", "Contact is required.");
validatePresenceOf("contactRelTypeID", "Resident relationship type is required.");
validatePresenceOf("effStartDate", "Effective Start Date is required.");
validatePresenceOf("relationshipid", "Relationship is required.");
if(this.getEffEndDate() != null) {
if(this.getEffEndDate().isBefore(this.getEffStartDate())) {
this.addError("effenddate", "End date must be on or after the start date.");
}
}
if(this.hasErrors()) {
throw new ValidationException(this);
}
}
}
Our CecilModel class we are extending the Model class.
package com.brookdale.model.activejdbc;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.axis.utils.StringUtils;
import org.apache.log4j.Logger;
import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.validation.ValidationBuilder;
import org.javalite.activejdbc.validation.ValidationException;
import org.javalite.activejdbc.validation.ValidatorAdapter;
import com.brookdale.core.CLArgs;
import com.brookdale.exception.CecilErrorsException;
import com.brookdale.message.CecilMessage;
import com.brookdale.model.Building;
import com.brookdale.security.bo.User;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import oracle.sql.DATE;
public abstract class CecilModel extends Model {
final static Logger logger = Logger.getLogger(CecilModel.class);
private static final transient TypeReference<HashMap<String, Object>> mapType = new TypeReference<HashMap<String, Object>>() {};
private static final transient TypeReference<ArrayList<HashMap<String, Object>>> listMapType = new TypeReference<ArrayList<HashMap<String, Object>>>() {};
//add -0600 to specify cental time zone
private static final transient SimpleDateFormat jsonDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
private transient Map<String, Collection<Map<String, Object>>> jsonInclude = new HashMap<>();
public Timestamp getUpdateDateTime() {
return getTimestamp("updateDateTime");
}
public void setUpdateDateTime(LocalDateTime updateDateTime) {
set("updateDateTime",updateDateTime == null ? null : Timestamp.valueOf(updateDateTime));
}
public Timestamp getCreateDateTime() {
return getTimestamp("createDateTime");
}
public void setCreateDateTime(LocalDateTime createDateTime) {
set("createDateTime",createDateTime == null ? null : Timestamp.valueOf(createDateTime));
}
public String getUpdateUsername() {
return getString("updateUsername");
}
public void setUpdateUsername(String updateUsername) {
set("updateUsername",updateUsername);
}
public String getCreateUsername() {
return getString("createUsername");
}
public void setCreateUsername(String createUsername) {
set("createUsername",createUsername);
}
public Long getUpdateTimeId() {
return getLong("updatetimeid");
}
public void setUpdateTimeId(Long updateTimeId) {
if (updateTimeId == null)
setLong("updatetimeid", 1);
else
setLong("updatetimeid",updateTimeId);
}
public void incrementUpdateTimeId() {
Long updatetimeid = this.getUpdateTimeId();
if (updatetimeid == null)
this.setUpdateTimeId(1L);
else
this.setUpdateTimeId(updatetimeid+1L);
}
public boolean save(User user) {
String userId = (CLArgs.args.isAuthenabled()) ? user.getUserid() : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
if (this.getId() == null || this.getId().toString().equals("0")) {
this.setId(null);
this.set("createDateTime", now);
this.set("createUsername", userId);
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", 1);
}
// update
else {
Long updatetimeid = this.getLong("updateTimeid");
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", updatetimeid == null ? 1 : updatetimeid + 1);
}
return super.save();
}
public boolean saveIt(User user) {
String userId = (CLArgs.args.isAuthenabled()) ? user.getUserid() : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
if (this.isNew()) {
this.setId(null);
this.set("createDateTime", now);
this.set("createUsername", userId);
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", 1);
}
// update
else {
Long updatetimeid = this.getLong("updateTimeid");
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", updatetimeid == null ? 1 : updatetimeid + 1);
}
return super.saveIt();
}
public boolean saveModel(User user, boolean insert) {
return saveModel(user.getUserid(), insert);
}
public boolean saveModel(String userId, boolean insert) {
userId = (CLArgs.args.isAuthenabled()) ? userId : "TEST_MODE";
if(insert){
return this.insertIt(userId);
}else{
return this.updateIt(userId);
}
}
public boolean insertIt(String user) {
user = (CLArgs.args.isAuthenabled()) ? user : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
this.set("createDateTime", now);
this.set("createUsername", user);
this.set("updateDateTime", now);
this.set("updateUsername", user);
this.set("updateTimeId", 1);
this.validate();
if(this.hasErrors()){
throw new ValidationException(this);
}
boolean inserted = super.insert();
if (!inserted)
throw new CecilErrorsException(new CecilMessage().error("Failed to insert " + this.getClass().getSimpleName()));
return inserted;
}
public boolean updateIt(String user) {
user = (CLArgs.args.isAuthenabled()) ? user : "TEST_MODE";
// update
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
this.set("updateDateTime", now);
this.set("updateUsername", user);
this.incrementUpdateTimeId();
this.validate();
if(this.hasErrors()){
throw new ValidationException(this);
}
boolean updated = super.save();
if (!updated)
throw new CecilErrorsException(new CecilMessage().error("Failed to update " + this.getClass().getSimpleName()));
return updated;
}
#Override
public <T extends Model> T set(String field, Object value) {
if (value instanceof LocalDate) {
return super.set(field, java.sql.Date.valueOf((LocalDate)value));
} else if (value instanceof LocalDateTime) {
return super.set(field, java.sql.Timestamp.valueOf((LocalDateTime)value));
} else {
return super.set(field, value);
}
}
public LocalDate getLocalDate(String field) {
if (field == null || "".equals(field))
return null;
else {
java.sql.Date d = getDate(field);
return d == null ? null : d.toLocalDate();
}
}
public void setLocalDate(String field, LocalDate value) {
if (value == null)
setDate(field, null);
else
setDate(field, java.sql.Date.valueOf(value));
}
public LocalDateTime getLocalDateTime(String field) {
java.sql.Timestamp d = getTimestamp(field);
return d == null ? null : d.toLocalDateTime();
}
public void setLocalDateTime(String field, LocalDateTime value) {
if (value == null)
setTimestamp(field, null);
else
setTimestamp(field, java.sql.Timestamp.valueOf(value));
}
}

The method Model.saveIt() will save the model attributes to a table if such a record (according to primary keys) already exists. If you are setting the primary keys to values not found in the database, this method will exit without doing much.
Additionally, there are a few issues in your code that are not idiomatic of JavaLite.
Update: based on your comment below, the framework will update the record if it is not "new", meaning if the PK or Composite Keys are not null, it will assume that you know what you are doing and will expect to find that record in the table by primary or composite keys, therefore if they key(s) are set and not null, it will always generate an UPDATE rather than insert. As a result, if you are setting primary keys to values not present in the table, the saveIt() or save() will do nothing. Please, see http://javalite.io/surrogate_primary_keys for more information.
Additionally, you can enable Logging to see what SQL it generates.

Related

Hibernate QueryException Named parameter not bound error

I keep getting the error org.hibernate.QueryException: Named parameter not bound : item when I start my transaction in JPA using EntityManager createNativeQuery. I have my code below utilizing the entity manager, along with my embeddedID class (for the composite key) and my persistence entity bean. Is there a problem in my query syntax? I am not sure as I've tried multiple ways of formatting the sql (coming from a properties file where there resides multiple sqls used throughout the project, and attempting to persist data to an oracle db). I am not sure why I keep falling on this error. I want to persist this data to my oracle database but this error keeps preventing that.
Query from query.properties file:
insertPromoData =INSERT INTO TEST.U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY, U_TIMESTAMP) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity, SYSDATE)
Embeddedable Class for establishing composite primary key on the target table:
#Embeddable
public class PromoID implements Serializable {
#Column(name = "ITEM")
private String item;
#Column(name = "LOC")
private String loc;
#Column(name = "WK_START")
private Date weekStart;
#Column(name = "TYPE")
private int type;
#Column(name = "FCSTID")
private String forecastId;
#Column(name = "U_TIMESTAMP")
private Timestamp insertTS;
public PromoID() {
}
public PromoID (String item, String loc, Date weekStart, int type, String forecastId, Timestamp insertTS) {
this.item = item;
this.loc = loc;
this.weekStart = weekStart;
this.type = type;
this.forecastId = forecastId;
this.insertTS = insertTS;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Date getWeekStart() {
return weekStart;
}
public void setWeekStart(Date weekStart) {
this.weekStart = weekStart;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getForecastId() {
return forecastId;
}
public void setForecastId(String forecastId) {
this.forecastId = forecastId;
}
public Timestamp getInsertTS() {
return insertTS;
}
public void setInsertTS(Timestamp insertTS) {
this.insertTS = insertTS;
}
//removed hashcode and equals methods for simplicity
Persistence Entity Bean:
#Entity
#Table(name = "U_USER_PROMO")
public class InsertPromoData {
#EmbeddedId
private PromoID id;
/*#Column(name="BATCH_ID")
String batchID;*/
#Column(name="ITEM")
String item;
#Column(name="LOC")
String loc;
#Column(name="WK_START")
String weekStart;
#Column(name="TYPE")
String type;
#Column(name="FCSTID")
String forecastId;
#Column(name="U_TIMESTAMP")
String insertTS;
#Column(name="NUMBER_OF_WEEKS")
String numberOfWeeks;
#Column(name="QTY")
String qty;
#Id
#AttributeOverrides(
{
#AttributeOverride(name = "item",column = #Column(name="ITEM")),
#AttributeOverride(name = "loc", column = #Column(name="LOC")),
#AttributeOverride(name = "weekStart", column = #Column(name="WK_START")),
#AttributeOverride(name = "type", column = #Column(name="TYPE")),
#AttributeOverride(name = "forecastId", column = #Column(name="FCSTID"))
}
)
public PromoID getId() {
return id;
}
public void setId(PromoID id) {
this.id = id;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public String getWeekStart() {
return weekStart;
}
public void setWeekStart(String weekStart) {
this.weekStart = weekStart;
}
public String getNumberOfWeeks() {
return numberOfWeeks;
}
public void setNumberOfWeeks(String numberOfWeeks) {
this.numberOfWeeks = numberOfWeeks;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getForecastId() {
return forecastId;
}
public void setForecastId(String forecastId) {
this.forecastId = forecastId;
}
public String getQty() {
return qty;
}
public void setQty(String qty) {
this.qty = qty;
}
public String getInsertTS() {
return insertTS;
}
public void setInsertTS(String insertTS) {
this.insertTS = insertTS;
}
}
My dao OracleImpl.java using EntityManager for persisting:
public void insertPromoData(List<InsertPromoData> insertData) {
logger.debug("Execution of method insertPromoData in Dao started");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
System.out.println("Beginning transaction for insertPromoData");
Query query = em.createNativeQuery(env.getProperty("insertPromoData"));
for (InsertPromoData promoData : insertData) {
query.setParameter("item", promoData.getItem());
query.setParameter("location", promoData.getLoc());
query.setParameter("wkStart", promoData.getWeekStart());
query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());
query.setParameter("type", promoData.getType());
query.setParameter("fcstId", promoData.getForecastId());
query.setParameter("quantity", Double.valueOf(promoData.getQty()));
}
query.executeUpdate();
System.out.println("Data for promo persisted");
em.getTransaction().commit();
}
catch(Exception e) {
logger.error("Exception in beginning transaction");
e.printStackTrace();
}
finally {
em.clear();
em.close();
}
logger.debug("Execution of method insertPromoData in Dao ended");
}
PromoValidator.java class:
List <InsertPromoData> insertPromos = new ArrayList<>();
promo.forEach(record -> {
if (record.getErrorList().size() == 0) {
rowsSuccessful++;
record.setItem(record.getItem());
record.setLoc(record.getLoc());
record.setNumber_Of_Weeks(record.getNumber_Of_Weeks());
record.setForecast_ID(record.getForecast_ID());
record.setType(record.getType());
record.setUnits(record.getUnits());
record.setWeek_Start_Date(record.getWeek_Start_Date());
insertPromos = (List<InsertPromoData>) new InsertPromoData();
for (InsertPromoData insertPromoData : insertPromos) {
insertPromoData.setItem(record.getItem());
insertPromoData.setLoc(record.getLoc());
insertPromoData.setWeekStart(LocalDate.parse(record.getWeek_Start_Date()));
insertPromoData.setNumberOfWeeks(Integer.parseInt(record.getNumber_Of_Weeks()));
insertPromoData.setType(Integer.parseInt(record.getType()));
insertPromoData.setForecastId(record.getForecast_ID());
insertPromoData.setQty(Double.parseDouble(record.getUnits()));
}
} else {
if (rowsFailure == 0) {
Util.writeHeaderToFile(templateCd, errorFile);
}
rowsFailure++;
Util.writeErrorToFile(templateCd, errorFile, record, record.getErrorList());
}
});
errorFile.close();
successFile.close();
OracleImpl.insertPromoData(insertPromos);
One of the reason this can happen is when insertData List you are passing is empty.
If I use below code ( please note that I have removed few columns to simplify it on my test environment with H2 database) - I get the error you described if empty list is passed and that's because there is indeed nothing to bind for the name parameter as the loop is not executed.
try {
em.getTransaction().begin();
System.out.println("Beginning transaction for insertPromoData");
Query query = em.createNativeQuery(
"INSERT INTO U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity)");
for (InsertPromoData promoData : insertData) {
query.setParameter("item", promoData.getId().getItem());
query.setParameter("location", promoData.getId().getLoc());
query.setParameter("wkStart", promoData.getId().getWeekStart());
query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());
query.setParameter("type", promoData.getId().getType());
query.setParameter("fcstId", promoData.getId().getForecastId());
query.setParameter("quantity", Double.valueOf(promoData.getQty()));
}
query.executeUpdate();
System.out.println("Data for promo persisted");
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
em.clear();
em.close();
}
The error I get is
org.hibernate.QueryException: Named parameter not bound : item
at org.hibernate.query.internal.QueryParameterBindingsImpl.verifyParametersBound(QueryParameterBindingsImpl.java:210)
at org.hibernate.query.internal.AbstractProducedQuery.beforeQuery(AbstractProducedQuery.java:1425)
at org.hibernate.query.internal.NativeQueryImpl.beforeQuery(NativeQueryImpl.java:249)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1610)
at com.danielme.blog.nativesql.dao.UserDao.insertPromoData(UserDao.java:99)
However - if I pass non-empty list - this works as expected
SQLCustomQuery:72 - Starting processing of sql query [INSERT INTO U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity)]
AbstractFlushingEventListener:74 - Flushing session
I also encountered same problem. I noticed that I was defining the parameter in the query but I was not setting its value in:
query.setParameter(parameterToBeSet,parameterValue)
For example,
String hql = "FROM COLLEGE FETCH ALL PROPERTIES WHERE studentId = :studentId AND departmentId = :departmentId AND studentName = :studentName";
DBConnectionManager.getInstance().invokeCallableOnSessionMasterDB(session -> {
Query<CollegeEntity> query = session.createQuery(hql);
query.setParameter("studentId", studentId);
query.setParameter("departmentId", departmentId);
values.addAll(query.list());
});
As you can see the student name value was not set. So, after adding:
query.setParameter("studentName", studentName);
It got solved.
GETRequest : localhost:8080/getbyCity/chennai,mumbai,kolkata -
error ---> when I send this request I got------->"Hibernate QueryException Named parameter not bound error".
Answer: when we send list of parameter we should mention the "/" at the End. ((( localhost:8080/getbyCity/chennai,mumbai,kolkata/ ))). Set the bound using "/".
In my case I have put same parameter name to the procedure as:
#Param("managementAccess") Boolean managementAccess,
#Param("managementAccess") String dealerCode,
#Param("managementAccess") String dealerName,
Here the parameter name is different but inside string the name is same.
Solution is:
#Param("managementAccess") Boolean managementAccess,
#Param("dealerCode") String dealerCode,
#Param("dealerName") String dealerName,

Why wrap GenericRowWithSchema using InternalRow in Dataset.collectFromPlan

Look at Dataset.collectFromPlan
private def collectFromPlan(plan: SparkPlan): Array[T] = {
val objProj = GenerateSafeProjection.generate(deserializer :: Nil)
plan.executeCollect().map { row =>
objProj(row).get(0, null).asInstanceOf[T]
}
}
the generated code for objProj is:
class SpecificSafeProjection extends org.apache.spark.sql.catalyst.expressions.codegen.BaseProjection {
private Object[] references;
private InternalRow mutableRow;
private Object[] values;
private org.apache.spark.sql.types.StructType schema;
public SpecificSafeProjection(Object[] references) {
this.references = references;
mutableRow = (InternalRow) references[references.length - 1];
schema = (org.apache.spark.sql.types.StructType) references[0];
}
public void initialize(int partitionIndex) {
}
public java.lang.Object apply(java.lang.Object _i) {
........
final org.apache.spark.sql.Row value = new org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema(values, schema);
if (false) {
mutableRow.setNullAt(0);
} else {
mutableRow.update(0, value);
}
return mutableRow;
}
}
And my question is:
The generated method SpecificSafeProjection.apply returns mutableRow: InternalRow who wraps value:GenericRowWithSchema, why not return value:GenericRowWithSchema directly??

Oracle Coherence index not working with ContainsFilter query

I've added an index to a cache. The index uses a custom extractor that extends AbstractExtractor and overrides only the extract method to return a List of Strings. Then I have a ContainsFilter which uses the same custom extractor that looks for the occurence of a single String in the List of Strings. It does not look like my index is being used based on the time it takes to execute my test. What am I doing wrong? Also, is there some debugging I can switch on to see which indices are used?
public class DependencyIdExtractor extends AbstractExtractor {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public Object extract(Object oTarget) {
if (oTarget == null) {
return null;
}
if (oTarget instanceof CacheValue) {
CacheValue cacheValue = (CacheValue)oTarget;
// returns a List of String objects
return cacheValue.getDependencyIds();
}
throw new UnsupportedOperationException();
}
}
Adding the index:
mCache = CacheFactory.getCache(pCacheName);
mCache.addIndex(new DependencyIdExtractor(), false, null);
Performing the ContainsFilter query:
public void invalidateByDependencyId(String pDependencyId) {
ContainsFilter vContainsFilter = new ContainsFilter(new DependencyIdExtractor(), pDependencyId);
#SuppressWarnings("rawtypes")
Set setKeys = mCache.keySet(vContainsFilter);
mCache.keySet().removeAll(setKeys);
}
I solved this by adding a hashCode and equals method implementation to the DependencyIdExtractor class. It is important that you use exactly the same value extractor when adding an index and creating your filter.
public class DependencyIdExtractor extends AbstractExtractor {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public Object extract(Object oTarget) {
if (oTarget == null) {
return null;
}
if (oTarget instanceof CacheValue) {
CacheValue cacheValue = (CacheValue)oTarget;
return cacheValue.getDependencyIds();
}
throw new UnsupportedOperationException();
}
#Override
public int hashCode() {
return 1;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof DependencyIdExtractor) {
return true;
}
return false;
}
}
To debug Coherence indices/queries, you can generate an explain plan similar to database query explain plans.
http://www.oracle.com/technetwork/tutorials/tutorial-1841899.html
#SuppressWarnings("unchecked")
public void invalidateByDependencyId(String pDependencyId) {
ContainsFilter vContainsFilter = new ContainsFilter(new DependencyIdExtractor(), pDependencyId);
if (mLog.isTraceEnabled()) {
QueryRecorder agent = new QueryRecorder(RecordType.EXPLAIN);
Object resultsExplain = mCache.aggregate(vContainsFilter, agent);
mLog.trace("resultsExplain = \n" + resultsExplain + "\n");
}
#SuppressWarnings("rawtypes")
Set setKeys = mCache.keySet(vContainsFilter);
mCache.keySet().removeAll(setKeys);
}

Why is my Udp.send using Akka.io always getting timeout?

Executing this code always results in timeout error and never sending UDP packet.
Why?
I need to write somthing more because stackoverflow won't let me to send the question... ;-), but I think the question is very simple and the code is all needed.
package controllers;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.dispatch.Recover;
import akka.io.Tcp;
import akka.io.Udp;
import akka.io.UdpMessage;
import akka.japi.Procedure;
import akka.util.ByteString;
import java.net.InetSocketAddress;
import static akka.pattern.Patterns.ask;
import play.libs.Akka;
import play.mvc.Result;
import play.libs.F.Function;
import play.libs.F.Promise;
import play.mvc.*;
public class Application extends Controller {
static ActorRef myActor = Akka.system().actorOf(Props.create(Listener.class));
public static Result index() {
return async(
Akka.asPromise(
//Promise.wrap(
ask(
myActor,
UdpMessage.send(ByteString.fromString("esto es una prueba"), new InetSocketAddress("172.80.1.81", 21001)),
1000
)
// .recover(
// new Recover<Object>() {
// #Override
// public Object recover(Throwable t) throws Throwable {
// if( t instanceof AskTimeoutException ) {
// Logger.error("Got exception: ", t);
// return internalServerError("Timeout");
// }
// else {
// Logger.error("Got exception: ", t);
// return internalServerError("Got Exception: " + t.getMessage());
// }
// }
// })
).map(
new Function<Object,Result>() {
public Result apply(Object response) {
return ok(response.toString());
}
}
)
);
}
//http://doc.akka.io/docs/akka/2.2-M2/java/io.html
//https://gist.github.com/kafecho/5353393
//how to terminate actor on shutdown http://stackoverflow.com/questions/10875101/how-to-stop-an-akka-thread-on-shutdown
public static class Listener extends UntypedActor {
final ActorRef nextActor;
public Listener() {
this(null);
}
public Listener(ActorRef nextActor) {
this.nextActor = nextActor;
// request creation of a bound listen socket
final ActorRef mgr = Udp.get(getContext().system()).getManager();
mgr.tell(UdpMessage.bind(getSelf(), new InetSocketAddress("localhost",
31001)), getSelf());
}
#Override
public void onReceive(Object msg) {
if (msg instanceof Udp.Bound) {
final Udp.Bound b = (Udp.Bound) msg;
getContext().become(ready(getSender()));
} else
unhandled(msg);
}
private Procedure<Object> ready(final ActorRef socket) {
return new Procedure<Object>() {
#Override
public void apply(Object msg) throws Exception {
if (msg instanceof Udp.Received) {
final Udp.Received r = (Udp.Received) msg;
// echo server example: send back the data
socket.tell(UdpMessage.send(r.data(), r.sender()),
getSelf());
// or do some processing and forward it on
final Object processed = new Object();//TODO parse data etc., e.g. using PipelineStage
if(nextActor!=null){
nextActor.tell(processed, getSelf());
}
} else if (msg.equals(UdpMessage.unbind())) {
socket.tell(msg, getSelf());
} else if (msg instanceof Udp.Unbound) {
getContext().stop(getSelf());
} else if (msg instanceof Udp.Send){
socket.tell(msg, getSelf());
} else
unhandled(msg);
}
};
}
}
}

ChoiceBox with custom Item in a TableView

I have a
private TableView<Indicators> tableviewIndicators;
with column
private TableColumn<Indicators, WindowsItem> tablecolumnFrame;
public static class WindowsItem {
CustomInternalWindow chrt;
private WindowsItem(CustomInternalWindow _chrt) {
chrt = _chrt;
}
public String toString() {
return chrt.getTitle();
}
}
private Indicators(String tl, WindowsItem chrt, String pne, Boolean sel) {
this.tool_col = new SimpleStringProperty(tl);
if (chrt == null) {
this.chart_col = new SimpleStringProperty("");
} else {
this.chart_col = new SimpleStringProperty(chrt.toString());
}
this.pane_col = new SimpleStringProperty(pne);
this.on_col = new SimpleBooleanProperty(sel);
this.chrt = chrt;
}
public String getTool() {
return tool_col.get();
}
public void setTool(String tl) {
tool_col.set(tl);
}
public WindowsItem getChart() {
return chrt;
}
public void setChart(WindowsItem _chrt) {
System.out.println("Indicators::setChart "+chrt.toString());
chrt = _chrt;
}
public String getPane() {
return pane_col.get();
}
public void setPane(String pne) {
pane_col.set(pne);
}
public Boolean getOn() {
return on_col.get();
}
public void setOn(boolean sel) {
on_col.set(sel);
}
public SimpleBooleanProperty onProperty() {
return on_col;
}
public SimpleStringProperty toolProperty() {
return tool_col;
}
public SimpleStringProperty chartProperty() {
return chart_col;
}
public SimpleStringProperty paneProperty() {
return pane_col;
}
}
tablecolumnFrame.setCellValueFactory(new PropertyValueFactory<Indicators, WindowsItem>("chart"));
How can I add a combobox or choicebox in tablecolumnFrame?
The following code
tablecolumnFrame.setCellFactory(new Callback<TableColumn<Indicators, WindowsItem>, TableCell<Indicators, WindowsItem>>() {
#Override
public TableCell<Indicators, WindowsItem> call(TableColumn<Indicators, WindowsItem> param) {
TableCell<Indicators, WindowsItem> cell = new TableCell<Indicators, WindowsItem>() {
#Override
public void updateItem(WindowsItem item, boolean empty) {
super.updateItem(item, empty);
if(empty){
return;
}
if (item != null) {
//final ChoiceBox<WindowsItem> choice = new ChoiceBox<>();
final ComboBox<WindowsItem> choice = new ComboBox<>();
int itemsInTab = chartsInTab.getChildren().size();// dimensione del contenuto del tab, compreso il pane
CustomInternalWindow winItem;
//
for (int i = 0; i < itemsInTab; i++) {
if (chartsInTab.getChildren().get(i) instanceof CustomInternalWindow) {
winItem = (CustomInternalWindow) chartsInTab.getChildren().get(i);
choice.getItems().add(new WindowsItem(winItem));
//choice.getItems().add(winItem.toString());
System.out.println("winItem.toString() "+winItem.toString());
}
}
return this error
SEVERE: javafx.scene.control.Control loadSkinClass Failed to load skin 'StringProperty [bean: TableRow[id=null, styleClass=cell indexed-cell table-row-cell], name: skinClassName, value: com.sun.javafx.scene.control.skin.TableRowSkin]' for control TableRow[id=null, styleClass=cell indexed-cell table-row-cell]
Why do you need special property? You can create ListView with ComboBox quite easily:
ObservableList<WindowsItem> windowsItems = FXCollections.observableArrayList();
ObservableList<WindowsItem> data = FXCollections.observableArrayList();
final ListView<WindowsItem> listView = new ListView<>(data);
listView.setEditable(true);
listView.setItems(data);
listView.setCellFactory(ComboBoxListCell.forListView(windowsItems));