In the JdbcPollingChannelAdapter, I think I understand how to use the createParameterSourceNoCache() method of the ExpressionEvaluatingSqlParameterSourceFactory class in order to get a non-caching SqlParameterSource object that can be applied to the JdbcPollingChannelAdapter's select parameters via its setSelectSqlParameterSource() method.
However, when it comes to update parameters, I only see it possible to set the update parameters via a SqlParameterSourceFactory through the setUpdateSqlParameterSourceFactory() method. From what I can tell, it is not possible to set the factory to be non-caching, only to call the non-caching create method of the factory to get a non-caching source object.
I need the update parameter to be the result of a dynamically calculated custom date that changes over time. I have a static method to dynamically calculate the result, and I was hoping I could use SpEL on the JdbcPollingChannelAdapter to evaluate the update parameter dynamically in the same way that the select parameter can do. Is this possible?
You can extend it and still inject it regular way into the JdbcPollingChannelAdapter:
public class NoCacheExpressionEvaluatingSqlParameterSourceFactory
extends ExpressionEvaluatingSqlParameterSourceFactory {
#Override
public SqlParameterSource createParameterSource(Object input) {
return createParameterSourceNoCache(input);
}
}
Related
I have just discovered contextSuperClass and have been experimenting with using it to provide scope annotations when building a symbol table in a first pass (I have a forward reference DSL).
I set the option in the grammar:
options {
tokenVocab=MyLexer;
language = CSharp;
contextSuperClass = interpreter.MyParserRuleContext;
}
and I have a class that derives from ParserRuleContext:
public class MyParserRuleContext : ParserRuleContext
{
public MyParserRuleContext()
{ }
public MyParserRuleContext(ParserRuleContext parent, int invokingStateNumber) : base(parent, invokingStateNumber)
{
}
public IScope ContextScope { get; set; }
}
So far so good. I use ParseTreeWalker with a listener (Enter/Exit methods) to walk the tree for the 1st pass and build the symbol table adding local scopes, etc into my ContextScope custom property.
The first issue is of course after the symbol table pass I am at the end of the token stream - the tree is walked.
The 2nd parse uses a visitor to evaluate the final result.
I have two questions:
How do I "reset" the parser so that it is at the root again without loosing scopes I have added into my custom property?
The second question is broader, but similar. Is this even a reasonable way to add scope annotations to the parse tree?
I have previously tried to use ParseTreeProperty<IScope> to add scope annotations, but the problem is similar. During the 2nd phase, the context objects provided in the visitor are not the same objects added to ParseTreeProperty<IScope> concurrent dictionary from the 1st pass - so they are not found. Between the 1st & 2nd passes I have only found parser.reset() as a way to start the parser over, and (of course) it appears to fully reset everything and I loose the any state I created in the 1st pass.
I am likely missing completely missing something here - so any help to put me in the right direction will be greatly appreciated.
I need to work with the reusable business objects for Sales tax, discounts, etc. and need to override some of the methods in these graph extensions. For example I am starting with the Opportunities graph. I have a set of order totals that need to calculate into the overall products amount and in the past we just overrode the tax attribute on (I think) tax category. Anyhow I don't see how its possible to use the PXOverrideAttribute on a method from a second level graph extension.
Here is my example:
public class OpportunityMaintExtOne : PXGraphExtension<PX.Objects.CR.OpportunityMaint.SalesTax, PX.Objects.CR.OpportunityMaint>
{
[PXOverride]
public virtual void CalcDocTotals(object row, decimal CuryTaxTotal, decimal CuryInclTaxTotal, decimal CuryWhTaxTotal,
Action<object, decimal, decimal, decimal> del)
{
del?.Invoke(row, CuryTaxTotal, CuryInclTaxTotal, CuryWhTaxTotal);
var someOtherTotal = Base1.Documents.Cache.GetValueAsDecimal<CROpportunityExtension.aMCurySomeOtherTotal>(row);
if (someOtherTotal == 0)
{
return;
}
var curyDocTotal = someOtherTotal + Base1.Documents.Cache.GetValueAsDecimal<CROpportunity.curyProductsAmount>(row);
Base1.Documents.Cache.SetValue<CROpportunity.curyProductsAmount>(row, curyDocTotal);
}
}
What is going on inside of CalcDocTotals in my graph extension is not the focus. It is the fact that I cannot override the OpportunityMaint.SalesTax CalcDocTotals method as I could if the method was in the first level (Base) graph. The SalesTax graph extension has the method as protected but protected methods (if it was in the base graph) are overrideable using the PXOverrideAttribute if you make your method call public which is what I have done. I also tried using a declared delegate in place of the Action but same results (as I expected but wanted to confirm).
My question: Is it possible to override a second, third, etc. level graph extension method using the PXOverrideAttribute?
When I compile the code above and the page loads I get this error:
Method Void CalcDocTotals(System.Object, System.Decimal,
System.Decimal, System.Decimal,
System.Action`4[System.Object,System.Decimal,System.Decimal,System.Decimal])
in graph extension is marked as [PXOverride], but the original method
with such name has not been found in PXGraph
The ability to override extension methods from a higher level extension has been added in 2018R1 Update 4 (18.104.0023). This resolves my question/issue and allows for the code posted in my question to function as is.
You cannot override methods from Extension1 in Extension2 etc as far as I've been able to see in my years with Acumatica. My solution to the problem was thus : Create a helper graph with your basic methodology, create a field or property for it in whatever graph you wish to use it in (Preferably a Lazy initialized one), then in whatever project you must override the logic on, just reference your original project, and create an extension of your helper graph.
I need to perform more action after the existing action is performed. For example, After Distribution > Sales Orders > Shipment > Action > Confirm Shipment, I need to populate all tracking numbers into another text box.
Please suggest.
The best thing here in my opinion would be to override the logic of the stock method. That will allow you to add your needed code without touching the base method as well as you being able to validate information before and after the base method is called.
In the case of your example, "Confirm Shipment" action ultimately executes the method "ConfirmShipment" which is defined as below:
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder)
{
.....
}
In order to customize the logic in here you have a few options.
Create an override method (added to the method queue, base called first then all 'override' methods)
Create an method that calls the stock one first, then your code. - this will in essence "replace" the stock logic but allow you to still call the base method. in doing this, you can run some checks before calling the base.
To do the second you would do the following
Create first the delegate in your code:
public delegate void ConfirmShipmentDelegate(SOOrderEntry docgraph, SOShipment shiporder)
Then define your override method:
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder, ConfirmShipmentDelegate baseMethod = null)
{
// Call our base method first if it exists
if (baseMethod != null)
{
baseMethod(docgraph,shiporder);
}
// Do my stuff here
}
Couple items to note here.
The definition has a third param to our delegate, this allows us to call the stock method and then do further work. It also tells the Acumatica framework our method should take priority over the stock method.
The stock method is called from the baseMethod call in the actual code.
Creating the extension this way allows for upgrades to occur without you having to totally redefine your method every time.
The second method would be just be an override of the stockcode. That is done with the following syntax
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder)
{}
When taking this approach, the stock method is first called, then your override method is called.
both of these would be handled in a graph extension defined as:
public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
Before attempting either, I would look at the articles in the Wiki on PXOverride as they give further examples/situations for these
I need to run some code whenever a property value is retrieved, so naturally it made sense to define the getProperty method in my class. This method will get automatically called whenever a property value is retrieved. Here's roughly what I have in my class:
class MyClass
{
def getProperty(String name)
{
// Run some code ...
return this.#"${name}"
}
}
The problem with the above method occurs when someone tries to make the following call somewhere:
MyClass.class
This call ends up in the getProperty method looking for a property named "class", however, there is not actual property named "class" so we get a MissingFieldException.
What would be the correct way to implement running code whenever a property value is retrieved and deal with these kind of situtations.
Best is not to have a getProperty method if not needed. If you need one and you want to fall back on standard Groovy logic, then you can use return getMetaClass().getProperty(this, property), as can be found in GroovyObjectSupport. This will cover more than just fields.
This seems to be a common problem with this method. Map has the same issue. The developers of groovy got around the problem with Map by saying you need to use getClass() directly.
I have ValidationMessages_en_US.properties as below
requiredFirstName=First name is required
requiredLastName=Last name is required
requiredEmailAddress=Email Address is required
...
...
What I would like to do is parameterize the field name in this. So something like this
requiredField={field} is required
So that there will be only one message and I can pass in the field name. I am using this in bean validations in the jsf environment.
This is where I want to use the values:
public class SomeBean implements Serializable
{
#NotNull(message="{requiredFirstName}" )
private String firstName;
......
.....
Is there a way to do this?
Thanks
There is no way to achieve this with the current Bean Validation specification or reference implementation (Hibernate Validator). You can interpolate the validated value and the constraint parameters and with Validator 5.1 you will also be able to add custom variables via HibernateConstraintValidatorContext (see also https://hibernate.atlassian.net/browse/HV-701). However, that does not help you yet to identify your fields and set the right 'field' value.