I am working with an agent-based simulation of an infectious disease epidemic in AnyLogic. I have two agents types in my model- Person and Building. I'm trying to write a function that counts the number of infectious contacts that the agent type 'Person' has at any given point in time. Below is my code for the function:
int infectedConnections = 0;
if (getConnections() != null)
for (Agent a : this.getConnections())
{
Person p = (Person) a;
if (p.IsCurrentlyInfected())
infectedConnections++;
}
return infectedConnections ;
The code compiles without any errors but during runtime, it throws up a java.lang.ClassCastException with the message: model.Building cannot be cast to model.Person.
When I try the same code with just one agent type (i.e. 'Person'), the model runs fine and the function returns the correct value. Could someone tell me how I could rectify my code so that I am able to run the function for 'Person' please?
If you just want to ignore agents of type Building, then you can do the following:
int infectedConnections = 0;
if (getConnections() != null) {
for (Agent a : this.getConnections())
{
if(a instanceof Person) {
Person p = (Person) a;
if (p.IsCurrentlyInfected()) {
infectedConnections++;
}
}
}
}
return infectedConnections;
The problem is that (Person) a; will fail if a is a Building instead of a Person.
Although Rob's answer solves your problem, note that having mixed Person and Building connections is really the 'root cause' of your problems: in general, mixing types in a collection of things is a design flaw for the type of reasons you're seeing (and probably your agents' connections to other Person agents or Building agents are two conceptually different relationships).
In AnyLogic you can have multiple networks per agent, not just the default connections one, by adding extra Link to agents elements. So, for example, your Person agent could have one for family relationships (say called family connecting to Person agents) and one for places they live/work in (say called workHomePlaces connecting to Building agents); obviously I'm inventing possible purposes of these networks.
Then you can do things like family.getConnections() and workHomePlaces.getConnections(), avoiding the issues you're encountering and having a more conceptually-correct design.
In the help, see
Agent Based Modeling --> Agent interaction --> Defining custom contact links.
Related
I am running a hierachical Spring Statemachine and - after walking through the inital transitions into state UP with the default substate STOPPED - want to use statemachine.getState(). Trouble is, it gives me only the parent state UP, and I cannot find an obvious way to retrieve both the parent state and the sub state.
The machine has states constructed like so:
StateMachineBuilder.Builder<ToolStates, ToolEvents> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial(ToolStates.UP)
.state(ToolStates.UP, new ToolUpEventAction(), null)
.state(ToolStates.DOWN
.and()
.withStates()
.parent(ToolStates.UP)
.initial(ToolStates.STOPPED)
.state(ToolStates.STOPPED,new ToolStoppedEventAction(), null )
.state(ToolStates.IDLE)
.state(ToolStates.PROCESSING,
new ToolBeginProcessingPartAction(),
new ToolDoneProcessingPartAction());
...
builder.build();
ToolStates and ToolEvents are just enums. In the client class, after running the builder code above, the statemachine is started with statemachine.start(); When I subsequently call statemachine.getState().getId(); it gives me UP. No events sent to statemachine before that call.
I have been up and down the Spring statemachine docs and examples. I know from debugging that the entry actions of both states UP and STOPPED have been invoked, so I am assuming they are both "active" and would want to have both states presented when querying the statemachine. Is there a clean way to achieve this ? I want to avoid storing the substate somewhere from inside the Action classes, since I believe I have delegated all state management issues to the freakin Statemachine in the first place and I would rather like to learn how to use its API for this purpose.
Hopefully this is something embarrasingly obvious...
Any advice most welcome!
The documentation describes getStates():
https://docs.spring.io/spring-statemachine/docs/current/api/org/springframework/statemachine/state/State.html
java.util.Collection<State<S,E>> getStates()
Gets all possible states this state knows about including itself and substates.
stateMachine.getState().getStates();
to wrap it up after SMA's most helpful advice: turns out the stateMachine.getState().getStates(); does in my case return a list of four elements:
a StateMachineState instance containing UP and STOPPED
three ObjectState instances containing IDLE, STOPPED and PROCESSING,
respectively.
this leads me to go forward for the time being with the following solution:
public List<ToolStates> getStates() {
List<ToolStates> result = new ArrayList<>();
Collection<State<ToolStates, ToolEvents>> states = this.stateMachine.getState().getStates();
Iterator<State<ToolStates, ToolEvents>> iter = states.iterator();
while (iter.hasNext()) {
State<ToolStates, ToolEvents> candidate = iter.next();
if (!candidate.isSimple()) {
Collection<ToolStates> ids = candidate.getIds();
Iterator<ToolStates> i = ids.iterator();
while (i.hasNext()) {
result.add(i.next());
}
}
}
return result;
}
This maybe would be more elegant with some streaming and filtering, but does the trick for now. I don't like it much, though. It's a lot of error-prone logic and I'll have to see if it holds in the future - I wonder why there isn't a function in the Spring Statemachine that gives me a list of the enum values of all the currently active states, rather than giving me everything possible and forcing me to poke around in it with external logic...
New to this website, and excited to share my first question :)
Ok so I'm going to be explaining what I have set-up currently so that my question can be understood better.
I have 2 java applications:
Logic Application (Where all the heavy load occurs)
Instrumented Application (Application instrumented into a running game)
What I do with these 2 applications is extract information from a game using the Instrumented Application then send it to the Logic Application.
The extraction of information/data is done through the Java Reflection API. Then after the information has been extracted, it is sent to the Logic Application through RMI (more on this below).
The reason I have 2 applications instead of 1 is because the game runs on Java 7 (old game), so the Instrumented Application runs on Java 7, and I can run the Logic application on whatever java version I want.
The way I transfer data/information between the 2 is through RMI (Remote Method Invocation).
Explanation: The Logic application invokes a getter method at the Instrumented App, and the method uses the Reflection API to grab the field value from the game it's instrumented into and return it.
Now as you guys have understood what I'm basically doing, now comes the challenge that I have been bamboozled by for quite some time.
Problem:
Most of the Field Values that are returned by Reflection are Serializable, therefore they pass-through RMI with no problem. But, some are Un-serializable objects like for an example "Item".
"Item" is an object and it holds 3 values: ID, Name, Quantity. So my thought was to make a wrapper and send the wrapper and it would be problem solved right? but no, another challenge popped up.
The challenge that popped up was: What if I needed to know the quantity of the object "Item" that I pulled out at another time? If my whole thing was 1 application, I would've used the Reflection API to get the Field using the Object by:
getClassLoader().loadClass("ItemClass").getDeclaredField("Item").get(ObjectThatIPreviouslyFetched);
But since I have to transfer the objects over to the Logic Application, I cannot transfer the Object itself "Item" so I have no way to return to that object and get updated information unless I look for the object again which is a waste of resources and makes my whole process slower.
Applications work like so:
Instrumented App -> Reflection -> Game -> Field Value (Object called Item) -> Wrapper -> RMI -> Logic Application (Object information is sent but Object itself can't be sent due to it being unserializable)
Summary of the question (using the pointers just above): How can I get the Object (Item) back so I can get updated information about it using Reflection.
This is the method I made to get the Field Values (Objects):
/**
*
* #param params owner;fieldName;multiplier
* #param object null if static
* #return returns the value of the object provided.
*/
public Object getFieldValue(String params, Object object) {
String[] paramsSplit = params.split(";");
try {
Class<?> clazz = classLoader.loadClass(paramsSplit[0]);
Field field = clazz.getDeclaredField(paramsSplit[1]);
field.setAccessible(true);
Object o = field.get(object);
if(!paramsSplit[2].equals("0")) return getMultipliedValue((Number) o,paramsSplit[2]);
else return o;
} catch (IllegalAccessException | NoSuchFieldError | ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
This method is found in the Logic Application and it attaches the Instrumented Application to the running game:
public void inject() {
VirtualMachine vm = null;
try {
vm = VirtualMachine.attach(String.valueOf(pid));
vm.loadAgent(Info.baseLocation());
} catch (AttachNotSupportedException | IOException |
AgentLoadException | AgentInitializationException e) {
e.printStackTrace();
} finally {
try {
if(vm != null) vm.detach();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I hope everything was understandable, I'm not an English native so I apologize if something seems wrong.
Thank you!
There's is no "Right" answer for this question.
I went for making a map that stores the objects, and assigned a unique key for every object. I then sent the object's unique key over RMI, now I can just get the Object using the unique key and send over the object's inner information at any time.
If the objects do not have circular references try JSON. GSON is recommended.
Another way would be to register them in memory using UnSafe then grabbing the objects using the address. Though you have to free it later on or else its scortched earth.
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.
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.
I'm trying to use jhat/OQL to trace a memory leak in our Tomcat container. The question I want to ask is:
"Show me all the instances (and sub-instances) of foo.bar.Cacheable class that are reachable from javax.servlet.http.HttpSession"
I managed to come up with the following, but this doesn't show subclasses of foo.bar.Cacheable (which is important since this is infact an interface).
select filter(reachables(s), "/foo.bar.Cacheable/(classof(it).name)") from javax.servlet.http.HttpSession s
I tried various permutations of the concept below, but just keep getting errors ("foo" is not defined).
select filter(reachables(s), classof(it) instanceof foo.bar.Cacheable) from javax.servlet.http.HttpSession s
Can anyone help me out with what I'm doing wrong to pose this question through OQL?
In jhat based OQL implementations (jHat, VisualVM) you can exploit the fact that you are not limited to the SQL like syntax but you have a complete javascript engine at your hands.
The following piece of code would do the trick
var containerSuperClass = "javax.servlet.http.HttpSession"
var elementSuperClass = "foo.bar.Cacheable"
// find the container class by name
var alClz = heap.findClass(elementSuperClass)
// retrieve all subclasses
var subClzs = alClz.subclasses()
// filter the list of objects reachables from instances of the container super class
// and all its subclasses so it contains only objects of classes from subClzs
map(heap.objects(containerSuperClass), 'filter(reachables(it), "it != null && contains(subClzs, containsClause(it))")')
// we need to externalize the contains clause because of clash in naming the closure parameter 'it'
function containsClause(rcbl) {
return function(it) {
if (rcbl == null || it == null) return false;
return it.name.equals(classof(rcbl).name)
}
}