StackOverflowError at jetbrains.exodus.entitystore.EntityIterableCache.putIfNotCached - java

My code is throwing the error below:
java.lang.StackOverflowError
at jetbrains.exodus.entitystore.EntityIterableCache.putIfNotCached(EntityIterableCache.java:100)
at jetbrains.exodus.entitystore.iterate.EntityIterableBase.asProbablyCached(EntityIterableBase.java:578)
at jetbrains.exodus.entitystore.iterate.EntityIterableBase.iterator(EntityIterableBase.java:138)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:72)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:59)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:55)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:23)
at jetbrains.exodus.entitystore.iterate.EntityIterableBase.iterator(EntityIterableBase.java:138)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:72)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:59)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:55)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:23)
at jetbrains.exodus.entitystore.iterate.EntityIterableBase.iterator(EntityIterableBase.java:138)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:72)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable$SortedIterator.<init>(MinusIterable.java:59)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:55)
at jetbrains.exodus.entitystore.iterate.binop.MinusIterable.getIteratorImpl(MinusIterable.java:23)
It does not point exactly where in my code is the root cause, but I know in my code I have this:
EntityIterable tempEntities = txn.findWithProp(entityType, propertyName);
tempEntities.forEach(entity -> {
if (!match(entity.getProperty(propertyName))) {
tempEntities = tempEntities.minus(txn.getSingletonIterable(entity));
}
);
And I know that the count for the tempEntities is 10,000+ items, since the code did a save for 10,000+ entities prior to this throwing.
Does it mean you can't iterate over like 10K entities with Xodus?

Obviously, you can iterate over 10K entities. Don't create iterables via singletons and binary operations (union, intersect, minus). This is API misusage. Even if you provide sufficient stack size for the JVM, performance problems would haunt you.

Related

How to verify PACT when data returns items with or without children (filled in or no existing array)

I'm using PACT and Java for contract tests and my issue is that I have an api where the items may come up like this:
[
{
"programCode": "ELA_NGL_G7_TX",
"contentResources": [
{
"tocPosition": 1827,
"contentIdentifier": "l_6bf0783e-8499-4f6c-9f9b-c8fbdc8dcf6b_e5f25016-e2fa-4223-8969-2004c644917d"
},
{
"tocPosition": 1828,
"contentIdentifier": "l_192af774-54b9-4280-87e9-71f2b86a7d4d_e5f25016-e2fa-4223-8969-2004c644917d",
"skills": [
{
"skillId": "ae836bd9-4758-4665-b3f8-8339313363e3",
"spineId": "63c2b7d0-cd69-4e8a-9761-c90623104b8c"
}
]
}
]
So as you can see, sometimes the inner skills array appears others it won't and not sure how to go about incorporating this scenario on my consumer tests. I mean, if the response had or no skills array depending on specific params, I could have two different tests and it might be fine, but here they come from the same call. So I guess what I need is something like an if else, that if the skills array is present then I would assert its inner children, otherwise just ignore it instead.
This is my consumer:
#ExtendWith(PactConsumerTestExt.class)
public class PublishContractWithTocGetSummaryTest {
Map<String, String> headers = new HashMap<>();
String getRecommendations = "/toc/getsummary/ELA_NGL_G7_TX";
#Pact(provider = "CRS-METADATA-FILTERING-SERVICE", consumer = "CRS-TOC-RECOMMENDER")
public RequestResponsePact createPact(PactDslWithProvider builder) throws IOException {
headers.put("Content-Type", "application/json");
DslPart body = new PactDslJsonBody()
.stringValue("programCode", "ELA_NGL_G7_TX")
.eachLike("contentResources")
.integerType("tocPosition", 0)
.stringType("contentIdentifier", "l_9d23cb4f-69dc-4032-bb53-73501234dc14_e5f25016-e2fa-4223-8969-2004c644917d")
.closeArray();
return builder
.given("get TOC Summary")
.uponReceiving("get TOC Summary")
.path(getRecommendations)
.method("GET")
.headers(headers)
.willRespondWith()
.status(200)
.body(body)
.toPact();
}
Many thanks.
The short answer to your question is that there isn't a way to do exactly what you want.
The longer answer about why that is not available is in the FAQs:
Why is there no support for specifying optional attributes?
Firstly, it is assumed that you have control over the provider's data (and consumer's data) when doing the verification tests. If you don't, then maybe Pact is not the best tool for your situation.
Secondly, if Pact supports making an assertion that element $.body.name may be present in a response, then you write consumer code that can handle an optional $.body.name, but in fact, the provider gives $.body.firstname, no test will ever fail to tell you that you've made an incorrect assumption. Remember that a provider may return extra data without failing the contract, but it must provide at minimum the data you expect.
The same goes for specifying "SOME_VALUE or null". If all your provider verification test data returned nulls for this key, you might think that you had validated the "SOME_VALUE", but in fact, you never had. You could get a completely different "SOME_VALUE" for this key in production, which may then cause issues.
The same goes for specifying an array with length 0 or more. If all your provider verification data returned 0 length arrays, all your verification tests would pass without you ever having validated the contents of the array. This is why you can only specify an array with minimum length 1 OR a zero length array.
Remember that unlike a schema, which describes all possible states of a document, Pact is "contract by examples". If you need to assert that multiple variations are possible, then you need to provide an example for each of those variations. Consider if it's really important to you before you do add a Pact test for each and every variation however. Remember that each interaction comes with a "cost" of maintenance and execution time, and you need to consider if it is worth the cost in your particular situation. You may be better off handling the common scenarios in the pact, and then writing your consumer to code to gracefully handle unexpected variations (eg. by ignoring that data and raising an alert).
https://docs.pact.io/faq#why-is-there-no-support-for-specifying-optional-attributes
So the TL;DR of Beth's answer:
Decide on what is valuable to test - empty arrays, non-empty or both
Use provider states to specify any variations on the response (consumer test)
Implement the state for the provider test to be able to control the response

Get product info in promotions applied in Hybris

I want to learn which promotions were applied to which products on promotionengine in order to distribute prices on products amongst themselves and send them to ERP.
When we look at the promotionService in Hybris, there is a method called getPromotionResults(order). It returns PromotionOrderResults object. In this object, two methods are related to my case, getAppliedProductPromotions() and getAppliedOrderPromotions().
If I did not miss it, I could not see product info for a promotion in these methods' results. Also, I looked at all attributes via promotion.getAppliedOrderPromotions().get(0).getAllAttributes() but i could not have them.
How can I know product info and discount amount in a promotion?
The method you are looking for is
PromotionOrderResults#getAppliedProductPromotions()
This will return all the promotions applied to order entries / products, you can navigate to the products via PromotionOrderEntryConsumed PromotionResult#getConsumedEntries()
I have a way to get the product that was Added as free gift on a promotion... Usually is something like this
Set promotionResultModels = cart.getAllPromotionResults();
if (!Objects.isNull(promotionResultModels))
{
Iterator resultsIterator = promotionResultModels.iterator();
while (resultsIterator.hasNext())
{
PromotionResultModel promoResultModel = (PromotionResultModel) resultsIterator.next();
Iterator var6 = promoResultModel.getActions().iterator();
while (var6.hasNext())
{
AbstractPromotionActionModel action = (AbstractPromotionActionModel) var6.next();
if (action instanceof RuleBasedOrderAddProductActionModel)
{
String freeGiftProductCode = ((RuleBasedOrderAddProductActionModel) action).getProduct().getCode();
}
}
}
}
However in my scenario, this is Free Gift promotion, not sure if the Bundle Based Promotion might have similar properties. As per the product that actually FIRED the promotion, I'm still looking a way to get it. The closest I've been is with this:
((RuleBasedOrderAddProductActionModel) action).getRule().getRuleContent()
However that's the Hybris Generated Code that has the RAO's and the product codes are buried within that string. So I needed to write an ugly script parser to find the codes.
Let me know if you find out the second part, the Products that triggered the promos, I'm still looking for it too.

Flatbuffers: how do you build nested tables?

I have a 3-level nested Java POJO that looks like this in the schema file:
struct FPathSegment {
originIata:ushort;
destinationIata:ushort;
}
table FPathConnection {
segments:[FPathSegment];
}
table FPath {
connections:[FPathConnection];
}
When I try to serialize a Java POJO to the Flatbuffer equivalent I pretty much get "nested serialzation is not allowed" error every time I try to use a common FlatBufferBuilder to build this entire object graph.
There is no clue in the docs to state if I have a single builder for the entire graph? A separate one for every table/struct? If separate, how do you import the child objects into the parent?
There are all these methods like create/start/add various vectors, but no explanation what builders go in there. Painfully complicated.
Here is my Java code where I attempt to serialize my Java POJO into Flatbuffers equivalent:
private FPath convert(Path path) {
FlatBufferBuilder bld = new FlatBufferBuilder(1024);
// build the Flatbuffer object
FPath.startFPath(bld);
FPath.startConnectionsVector(bld, path.getConnections().size());
for(Path.PathConnection connection : path.getConnections()) {
FPathConnection.startFPathConnection(bld);
for(Path.PathSegment segment : connection.getSegments()) {
FPathSegment.createFPathSegment(bld,
stringCache.getPointer(segment.getOriginIata()),
stringCache.getPointer(segment.getDestinationIata()));
}
FPathConnection.endFPathConnection(bld);
}
FPath.endFPath(bld);
return FPath.getRootAsFPath(bld.dataBuffer());
}
Every start() method throws a "FlatBuffers: object serialization must not be nested" exception, can't figure out what is the way to do this.
You use a single FlatBufferBuilder, but you must finish serializing children before starting the parents.
In your case, that requires you to move FPath.startFPath to the end, and FPath.startConnectionsVector to just before that. This means you need to store the offsets for each FPathConnection in a temp array.
This will make the nesting error go away.
The reason for this inconvenience is to allow the serialization process to proceed without any temporary data structures.

Getting All Workitems from Team Area

I have the following objects:
ITeamRepository repo;
IProjectArea projArea;
ITeamArea teamArea;
The process of obtaining the projArea and the teamArea is quite straightforward (despite the quantity of objects involved). However I can't seem to find a way to obtain a list with all the Workitems associated with these objects in a direct way. Is this directly possible, probably via the IQueryClient objects?
This 2012 thread (so it might have changed since) suggests:
I used the following code to get the work items associated with each project area:
auditableClient = (IAuditableClient) repository.getClientLibrary(IAuditableClient.class);
IQueryClient queryClient = (IQueryClient) repository.getClientLibrary(IQueryClient.class);
IQueryableAttribute attribute = QueryableAttributes.getFactory(IWorkItem.ITEM_TYPE).findAttribute(currProject, IWorkItem.PROJECT_AREA_PROPERTY, auditableClient, null);
Expression expression = new AttributeExpression(attribute, AttributeOperation.EQUALS, currProject);
IQueryResult<IResolvedResult<IWorkItem>> results = queryClient.getResolvedExpressionResults(currProject, expression, IWorkItem.FULL_PROFILE);
In my code, currProject would be the IProjectArea pointer to the current project as you loop through the List of project areas p in your code.
The IQueryResult object 'results' then contains a list of IResolvedResult records with all of the work items for that project you can iterate through and find properties for each work item.

Facing OutOfMemory issue in Java

I am facing out of memory issue due to high heap allocation.I verified it from HP Diagnostics tool and it is pointing to a section in my code where I am adding elements in an arraylist. I am not able o figure out how else can I write this code so that objects are released early. Below is the code :
private List<UpperDTO> populateRecords(List<BaseEntity> baseEntityList,List<DataEntity> dataEntityList) {
List<UpperDTO> masterDTOList = new ArrayList<UpperDTO>();
if(baseEntityList !=null && baseEntityList.size()>0){
BigDecimal conId = null;
for(BaseEntity baseEntity :baseEntityList){
conId = baseEntity.getConsignmentId();
ArrayList<StatusData> statusDataList = new ArrayList<StatusData>();
if(dataEntityList !=null && dataEntityList.size()>0){
for(DataEntity data : dataEntityList){
if(conId.equals(data.getConsignmentId())){
//making null to supress from the response
data.setConsignmentId(null);
statusDataList.add(TrackServiceHelper.convertStatusDataToDTO(data));
}
}
}
masterDTOList.add(TrackServiceHelper.populateDTO(baseEntity, statusDataList));
}
}
return masterDTOList;
}
public static UpperDTO populateDTO(TrackBaseEntity baseEntity,
List<StatusData> statusList) {
UpperDTO upperDTO = new UpperDTO();
//Setter methods called
upperDTO.setStatusData(statusList);
return upperDTO;
}
The issue is pointed at following line in the code :
masterDTOList.add(TrackServiceHelper.populateDTO(baseEntity, statusDataList));
This is rest api which receives messages from JMS Queues and MDB listens to these messages. I am not able to simulate this in my local or Dev environments as the issue comes during performance testing when the number of requests are high. How can I fix this?
This is the stacktrace of Collection Leak from HP Diagnostics:
Chart Collection Class Contained Type Probe Collection Growth Rate Collection Size Leak Stack Trace Maximum Size
0, 0, 255 java.util.ArrayList com.rex.ih2.dtos.UpperDTO gtatsh645 3,848 122,312 java.util.ArrayList.add(ArrayList.java:413)
com.rex.ih2.utils.AppDAO.populateConsignment(AppDAO.java:168)
com.rex.ih2.utils.AppDAO.searchConsignment(AppDAO.java:93)
com.rex.ih2.service.AppService.fetchConDetail(AppService.java:131)
com.rex.ih2.service.AppService.getConDetail(AppService.java:69)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:76)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:607)
org.apache.webbeans.intercept.InterceptorHandler.invoke(InterceptorHandler.java:297)
org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:98)
com.rex.ih2.service.TrackService_$$_javassist_0.getConsignmentDetail(TrackService_$$_javassist_0.java)
com.rex.ih2.beans.TrackBean.action(TrackBean.java:35)
com.tnt.integration.bean.AbstractServiceBean.invokeService(AbstractServiceBean.java:259)
com.tnt.integration.bean.AbstractServiceBean.onMessage(AbstractServiceBean.java:157)
com.rex.ih2.beans.TrackBean.onMessage(TrackBean.java)
I agree with dcsohi. This is actually a design problem. You may want to look at below approaches:-
1) Size of the object being added in the list. If it can be optimized.
2) Handle data in chunks instead of adding all at once in the list.
3) Optimizing JVM arguments to increase head size so that it can handle more objects.
You can try to simulate this by increasing number of test objects and reducing heap size in dev environment or maybe taking production dump and running with the same volume.
Ok, it looks to me like you only care about DataEntity objects and BaseEntity objects where their "consignment IDs" match. You really should do this sort of thing in the database query. The use of "entity" objects makes it seem like your DB interactions are via JPA/Hibernate, in which case you may want to create a DB view that joins the two tables by consignment ID, and provides the necessary information for your output. Next, create a custom read-only entity that matches this view. Then you can apply pagination to your query of this view (if it's still necessary) and retrieve the information in smaller batches.

Categories