Runtime error when try to retrieve the detail records, due to generated select
MIX of PXSelector and PXDBCalc, and inheritance just for fun
When try to pull up an existing record (NOT use the selector), it's failing on the SQL
Not sure how much anyone might help, but wanted to report something regardless...
Seems to be a mismatch of the parameters:
--#P0='INV',#P1=4899,#P2=N'USD',#P3=N'AR005697'
Taken from SQL Profiler, and bunch of where clauses chopped out. Key issue is P1 - In sub select it should be P3, right now it's giving me:Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the nvarchar value 'AR005747' to data type int.
Quite a mess of logic, but here is the partial select:
SELECT
*,
(
SELECT
TOP (1) SUM( [XPMPaymentHdrAssocDoc].[Amount])
FROM
[XPMPaymentHdrAssocDoc] [XPMPaymentHdrAssocDoc]
INNER JOIN
[XPMPaymentHdr] [XPMPaymentHdr]
ON
(
[XPMPaymentHdr].[CompanyID] = 2)
AND [XPMPaymentHdr].[PaymentID] = [XPMPaymentHdrAssocDoc].[PaymentID]
WHERE
(
[XPMPaymentHdrAssocDoc].[CompanyID] = 2)
AND (
[XPMPaymentHdrAssocDoc].[AssocDocType] = #P0
AND **[XPMPaymentHdrAssocDoc].[AssocDocID] = #P1**
)
)
FROM
[ARRegister] [XPMARRegister]
WHERE
(
[XPMARRegister].[CompanyID] = 2)
AND ( (
[XPMARRegister].[DocType] = #P0
AND **[XPMARRegister].[CustomerID] = #P1**
AND [XPMARRegister].[CuryID] = #P2)
AND (
[XPMARRegister].[RefNbr] = #P3))
--#P0='INV',**#P1=4899**,#P2=N'USD',#P3=N'AR005697'
How - Great pile of fun...
DAC (partial, lots removed for clarity. PXUnboundDefault worked, but the PXDBScalar fails)
Worked - Selects fine. BUT can't use in the PXRestriction of a selector later on....
[System.SerializableAttribute()]
[PXHidden]
public class XPMARRegister : ARRegister
{
#region Inherited Fields
public abstract class docType : PX.Data.BQL.BqlString.Field { }
public abstract class refNbr : PX.Data.BQL.BqlString.Field { }
public abstract class curyInfoID : PX.Data.BQL.BqlLong.Field { }
public abstract class curyDocBal : PX.Data.BQL.BqlDecimal.Field { }
public abstract class docBal : PX.Data.BQL.BqlDecimal.Field { }
public abstract class released : PX.Data.BQL.BqlBool.Field { }
public abstract class openDoc : PX.Data.BQL.BqlBool.Field { }
public abstract class hold : PX.Data.BQL.BqlBool.Field { }
#endregion
public abstract class xPMPaymentHdrAssocDocUnrelasedPaymentAmount : PX.Data.IBqlField
{
}
//[PXUnboundDefault(typeof(Select5<
// XPMPaymentHdrAssocDoc,
// InnerJoin<XPMPaymentHdr,
// On<XPMPaymentHdr.paymentID, Equal<XPMPaymentHdrAssocDoc.paymentID>>>,
// Where<XPMPaymentHdrAssocDoc.assocDocType, Equal<Current<XPMARRegister.docType>>,
// And<XPMPaymentHdrAssocDoc.assocDocID, Equal<Current<XPMARRegister.refNbr>>,
// And<Where<XPMPaymentHdr.status, Equal<PaymentStatusList.applied>,
// Or<XPMPaymentHdr.status, Equal<PaymentStatusList.eligibleforSubmission>,
// Or<XPMPaymentHdr.status, Equal<PaymentStatusList.open>,
// Or<XPMPaymentHdr.status, Equal<PaymentStatusList.approved>>>>>>>>,
// Aggregate<
// Sum<XPMPaymentHdrAssocDoc.curyAmount, Sum<XPMPaymentHdrAssocDoc.amount>>>>), SourceField = typeof(XPMPaymentHdrAssocDoc.amount), PersistingCheck = PXPersistingCheck.Nothing)]
[PXDBScalar(typeof(Search5<
XPMPaymentHdrAssocDoc.amount,
InnerJoin<XPMPaymentHdr,
On<XPMPaymentHdr.paymentID, Equal<XPMPaymentHdrAssocDoc.paymentID>>>,
Where<XPMPaymentHdrAssocDoc.assocDocType, Equal<Current<XPMARRegister.docType>>,
And<XPMPaymentHdrAssocDoc.assocDocID, Equal<Current<XPMARRegister.refNbr>>,
And<Where<XPMPaymentHdr.status, Equal<PaymentStatusList.applied>,
Or<XPMPaymentHdr.status, Equal<PaymentStatusList.eligibleforSubmission>,
Or<XPMPaymentHdr.status, Equal<PaymentStatusList.open>,
Or<XPMPaymentHdr.status, Equal<PaymentStatusList.approved>>>>>>>>,
Aggregate<Sum<XPMPaymentHdrAssocDoc.amount>>>))]
[PXDecimal(4)]
public virtual Decimal? XPMPaymentHdrAssocDocUnrelasedPaymentAmount
{
get;
set;
}
}
Used within 2nd DAC (again, greatly reduced):
ROUGH logic - I want open invoices, with a balance, reduced by my own payment amount
Failing, apparently, due to THIS PXSelector
[System.SerializableAttribute()]
[PXPrimaryGraph(typeof(XPARInvoicePayment))]
[PXCacheName(Messages.CacheXPMPayAppDet)]
public class XPMPayAppDetAR : XPMPayAppDet
{
#region AssocDocModule
[PXDBString(2, IsFixed = true)]
[PXUIField(DisplayName = "Document Module")]
[PXDefault(AssocDocModuleList.AccountReceivableKey)]
[AssocDocModuleList.List()]
public override String AssocDocModule { get; set; }
#endregion AssocDocModule
#region AssocDocType
public new abstract class assocDocType : PX.Data.BQL.BqlString.Field<assocDocType>
{
}
[PXDBString(3, IsFixed = true)]
[ARDocType.List()]
[PXDefault(ARDocType.Invoice)]
[PXUIField(DisplayName = "Associated Document Type")]
public override String AssocDocType { get; set; }
#endregion AssocDocType
#region AssocDocID
public new abstract class assocDocID : PX.Data.BQL.BqlString.Field<assocDocID>
{
}
[PXDBString(15, IsUnicode = true)]
[PXUIField(DisplayName = "Document ID")]
**[PXSelector(typeof(Search<XPMARRegister.refNbr, Where<XPMARRegister.docType, Equal<Current<XPMPayAppDetAR.assocDocType>>, And<XPMARRegister.customerID, Equal<Current<XPMPayAppHdr.customerID>>, And<XPMARRegister.curyID, Equal<Current<XPMPayAppHdr.curyID>>>>>>), DescriptionField = typeof(XPMARRegister.docDesc))]**
[PXRestrictor(typeof(Where<XPMARRegister.hold, Equal<False>>), Messages.DocumentOnHold)]
[PXRestrictor(typeof(Where<XPMARRegister.openDoc, Equal<True>>), Messages.DocumentNotOpen)]
[PXRestrictor(typeof(Where<XPMARRegister.released, Equal<True>>), Messages.DocumentUnreleased)]
[PXRestrictor(typeof(Where<XPMARRegister.docBal, Greater<decimal0>>), Messages.DocumentNotOpen)]
// [PXRestrictor(typeof(Where<XPMARRegister.docBalLessUnrelased, Greater<decimal0>>), Messages.DocumentNotOpen)]
[PXCheckUnique(typeof(XPMPayAppDetAR.xPAppID), typeof(XPMPayAppDetAR.assocDocModule), typeof(XPMPayAppDetAR.assocDocType), typeof(XPMPayAppDetAR.assocDocID), IgnoreNulls = false, ClearOnDuplicate = true)]
public override String AssocDocID { get; set; }
#endregion AssocDocID
}
Graph, not that it's very interesting (again, highly reduced):
public class XPARInvoicePayment : PXGraph<XPARInvoicePayment, XPMPayAppHdr>
{
public ToggleCurrency<XPMPayAppHdr> CurrencyView;
public PXSelect<XPMPayAppHdr> Document;
public PXSelect<XPMPayAppDet, Where<XPMPayAppDet.xPAppID, Equal<Current<XPMPayAppHdr.xPAppID>>>> DetailsAll;
**public PXSelect<XPMPayAppDetAR, Where<XPMPayAppDetAR.xPAppID, Equal<Current<XPMPayAppHdr.xPAppID>>, And<XPMPayAppDetSO.assocDocModule, Equal<AssocDocModuleList.accountReceivable>>>> DetailsAR;**
public PXSelect<XPMPayAppDetSO, Where<XPMPayAppDetSO.xPAppID, Equal<Current<XPMPayAppHdr.xPAppID>>, And<XPMPayAppDetSO.assocDocModule, Equal<AssocDocModuleList.salesOrder>>>> DetailsSO;
public PXSetup<XPMSetup> PaymentSetup;
}
When using toList() ConstraintCollector in optaplanner 8.1 like:
factory.from(Lesson.class)
.groupBy(Lesson::getCourse, ConstraintCollectors.toList()).penalize(...);
I run into:
Exception executing consequence for rule "foo" in model: java.lang.ClassCastException: class model.Lesson cannot be cast to class java.util.List (model.Lesson is in unnamed module of loader 'app'; java.util.List is in module java.base of loader 'bootstrap')
at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
Question: Is this a optaplanner bug, or is my code wrong?
The most simple complete reproducer I find is:
#PlanningSolution
public class OptaplannerIssue2 implements ConstraintProvider {
#Override
public Constraint[] defineConstraints(ConstraintFactory factory) {
return new Constraint[] {factory.from(IssueEntity.class)
.groupBy(IssueEntity::getValue, ConstraintCollectors.toList())
.penalize("x", HardSoftScore.ofHard(1), (entity, enityList) -> 2)};
}
#PlanningScore
private HardSoftScore score = HardSoftScore.ZERO;
#PlanningEntityCollectionProperty
private final List<IssueEntity> entities = new ArrayList<IssueEntity>();
public List<IssueEntity> getEntities() {
return entities;
}
#ValueRangeProvider(id = "valueRange")
public CountableValueRange<Integer> getValueRange() {
return ValueRangeFactory.createIntValueRange(0, 4);
}
public static void main() {
// create Entity
OptaplannerIssue2 issue = new OptaplannerIssue2();
IssueEntity e1 = new IssueEntity();
issue.entities.add(e1);
// solve
SolverFactory<OptaplannerIssue2> solverFactory = SolverFactory.create(new SolverConfig()
.withEnvironmentMode(EnvironmentMode.FULL_ASSERT).withSolutionClass(OptaplannerIssue2.class)
.withEntityClasses(IssueEntity.class)
.withScoreDirectorFactory(
new ScoreDirectorFactoryConfig().withConstraintProviderClass(OptaplannerIssue2.class))
.withTerminationConfig(new TerminationConfig().withSecondsSpentLimit(5L)).withPhases(
new ConstructionHeuristicPhaseConfig()
.withConstructionHeuristicType(ConstructionHeuristicType.FIRST_FIT),
new LocalSearchPhaseConfig().withLocalSearchType(LocalSearchType.LATE_ACCEPTANCE)));
Solver<OptaplannerIssue2> solver = solverFactory.buildSolver();
solver.solve(issue);
}
}
With the following entity-class:
#PlanningEntity
public class IssueEntity {
#PlanningVariable(valueRangeProviderRefs = {"valueRange"})
Integer value;
public Integer getValue() {
return value;
}
}
In the related thread: Optaplanner GroupBy with toList not working as expected the questioner didn't provide all information to commentators trying to help and when I provided reproducer there I got deleted, so I had to ask new question.
The behavior you describe is a bug in OptaPlanner, which we have now fixed. Please upgrade to the next release of OptaPlanner, which at the time of writing this answer will be OptaPlanner 8.2.0.
For details, see PLANNER-2305.
I am having an issue with storing data to Cassandra table from apache ignite when I am trying to insert into a column of list data type in Cassandra
Cassandra table:
CREATE TABLE business_categories (
id int,
category_name TEXT,
sub_categories list<TEXT>,
PRIMARY KEY(category_name, id)
);
xml file:
<persistence keyspace="ignite" table="business_categories">
<keyspaceOptions>
REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1}
AND DURABLE_WRITES = true
</keyspaceOptions>
<tableOption>
comment = 'Cache test'
AND read_repair_chance = 0.2
</tableOption>
<keyPersistence class="com.cache.business.model.BusinessCategoriesKey" strategy="POJO"/>
<valuePersistence class="com.cache.business.model.BusinessCategoriesValue" strategy="POJO"/>
</persistence>
key class object:
public class BusinessCategoriesKey implements Serializable {
private static final long serialVersionUID = 581472167344584014L;
private int id;
private String category_name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategory_name() {
return category_name;
}
public void setCategory_name(String category_name) {
this.category_name = category_name;
}
}
value class object:
public class BusinessCategoriesValue implements Serializable {
private static final long serialVersionUID = -1694694702874919854L;
private List<String> sub_categories = new ArrayList<>();
public List<String> getSub_categories() {
return sub_categories;
}
public void setSub_categories(List<String> sub_categories) {
this.sub_categories = sub_categories;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
I am getting the below error message
Caused by: com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [list <-> java.nio.HeapByteBuffer]
The sub_categories field is a java.util.List and it seems Apache Ignite does not provide a direct mapping to appropriate Cassandra type for such kind of Java types.
So, this field could be persisted into Cassandra only if you manually specify all mapping details for the object type and if field type itself is implementing java.io.Serializable interface.
In such case, the field will be persisted into a separate table column as a blob.
Please try to modify your code in the following way:
CREATE TABLE business_categories (
id int,
category_name text
sub_categories blob,
PRIMARY KEY(category_name, id)
);
Persistence descriptor:
<persistence keyspace="ignite" table="business_categories">
<keyspaceOptions>
REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1}
AND DURABLE_WRITES = true
</keyspaceOptions>
<tableOption>
comment = 'Cache test'
AND read_repair_chance = 0.2
</tableOption>
<keyPersistence class="com.cache.business.model.BusinessCategoriesKey" strategy="POJO"/>
<valuePersistence class="com.cache.business.model.BusinessCategoriesValue"
strategy="POJO"
serializer="org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer">
<field name="sub_categories" column="sub_categories"/>
</valuePersistence>
You can find additional details here: Cassandra Integration Examples
with following code I am getting error Persistence entity must not be null. what could be the mistake.
public interface DistrictRepo extends PagingAndSortingRepository<District, Integer> {
#Query(
"select d.districtId, d.districtName from District d where d.districtId in (:districtIds) group by d.districtId"
)
#RestResource(path="byList")
List<Object[]> byList(#Param("districtIds") List<Integer> districtIds);
}
If you are going to make a "search" method, use this approach:
#Projection(name = "idAndName", types = {District.class})
public interface IdAndName {
Integer getId();
String getName();
}
#RestResource(path="byIds", rel="byIds")
#Query("select d from District d where d.districtId in (:districtIds)")
List<District> findByIds(#Param("ids") Integer... ids);
Then use this url:
http://localhost:8080/api/districts/search/byIds?ids=1,2,3&projection=idAndName
More info about projection
If you need to use complex queries with grouping and aggregation that return DTOs you can not use "search" methods. Instead you have to implement custom controller, for example:
#RepositoryRestController
#RequestMapping("/districts")
public class DistrictController {
#Autoware
private DistrictRepo repo;
#GetMapping("/report")
public ResponseEntity<?> report(#RequestParam(value = "ids") Integer... ids) {
List<Dto> dtos = repo.getDtosByIds(ids);
return ResponseEntity.ok(new Resources<>(dtos));
}
}
Where Dto is something like this:
#Data // This is Lombok annotation (https://projectlombok.org/)
#Relation(value = "district", collectionRelation = "districts")
public class Dto {
private final Integer id;
private final String name;
}
And something like this the repo method:
public interface DistrictRepo extends PagingAndSortingRepository<District, Integer> {
#Query("select new ...Dto(d.districtId, d.districtName) from District d where d.districtId in (:districtIds) group by d.districtId")
#RestResource(path="byList", rel="byList")
List<Dto> getDtosByIds(#Param("ids") Integer... ids);
}
More info.
I'm aware that this problem has been asked several times before. But I believe I have a very different case, I'm currently encountering this error when invoking the getResultList() method, not when persisting.
Note that I'm using:
-javaee6
-seam3-security
-jboss7.1.3
-postgresql
Series of events:
1.) After login, I saved my user in picketlink using the interface org.picketlink.idm.api.User:
setUser(new MyUser(user));
I should be able to retrieve the user using ((MyUser)identity.getuser()).getUser();
2.) Now I have a BusinessAccount entity that has OneToMany relationship with AccounType:
#Entity
#Table(name = "T_ACCOUNT")
public class BusinessAccount extends BaseEntity {
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "ACCOUNT_TYPE_ID")
private AccountType accountType;
}
#Entity()
#Table(name = "T_ACCOUNT_TYPE")
public class AccountType extends BaseEntity {
#Enumerated(EnumType.STRING)
#Column(name = "ACCOUNT_TYPE", length = 20)
private AccountTypeEnum accountTypeEnum;
}
My problem is I have a service: BusinessAccountService that extends BaseService, which calls getAccounts and it throws this error:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing
BaseService has:
public User getCurrentUser() {
if(currentUser==null){
try {
currentUser=((MyUser) identity.getUser()).getUser();
} catch(Exception e){
log.warn("getCurrentUser cannot retrieve current user from session identity and currentUser has not been set programmatically");
}
}
return currentUser;
}
And then my dynamically generated query is like this:
select distinct a from BusinessAccount a where a.accountType.accountTypeEnum=:a_accountType_accountTypeEnum and (a.accountType in (:a_accountType0))
Param name:a_accountType_accountTypeEnum value:serviceProvider
Param name:a_accountType0 value:[org.model.accounts.AccountType#1, org.model.accounts.AccountType#2]
and I found out that this line is throwing the error:
and (a.accountType in (:a_accountType0))
Why is that? When I'm only executing a getResultList()?
I think I've found the problem, the AccountType is extending a BaseEntity that has a Version field. When I removed the extend and add Version property in AccountType, I got the same error.
The Version field:
#Version
#Column(name = "VERSION")
private Integer version;
This version field must have an initial value which is 0.