OpenEdge 4GL REST Service : computing temp table values creating errors - openedge

I have a progress 4gl rest webservice. The Create method accepts a dataset from which I extract its underlying temp table
METHOD PUBLIC VOID Createprices(INPUT-OUTPUT DATASET dsprices):
DEFINE VARIABLE hT AS HANDLE.
ht = DATASET dsprices:GET-BUFFER-HANDLE(TEMP-TABLE ttprices:NAME).
ht = ht:DEFAULT-BUFFER-HANDLE.
PreTransactionValidate(INPUT-OUTPUT TABLE-HANDLE ht).
I then pass the temp-table buffer to another method (pretransactionvalidate) where I compute the values for a couple of fields.
The PretransactionValidate method with dummy values being assigned -
METHOD PUBLIC VOID PreTransactionValidate( INPUT-OUTPUT table-handle ttprices):
FOR EACH ttprices:
ASSIGN
ttprices.PricesId = NEXT-VALUE(SeqPricesId)
ttprices.AddedDate = TODAY
ttprices.AddedTime = TIME.
END.
Calling the PretransactionValidate method causes my Create Method to fail. If I comment out the call, I can successfully create a record. I'm a Progress newbie and can't find much material on the net, so any help would be worth trying.
Cheers

In your Createprices method, ht is assigned to the handle of a buffer, but your procedure PreTransactionValidate expects a dataset handle.
As both methods are in the same compile unit (class), it's not required to pass the temp-table as a parameter anyway. Temp-tables are (unfortunately) always class-global in the ABL.
If both methods would be in different compile units, you could pass the temp-table directly:
<some_object_reference>:PreTransactionValidate (INPUT-OUTPUT TABLE ttprices).

Related

Accessing pubsublite message attributes in beam pipeline - Java

We have been using PubSubLite in our Go program without any issues and I just started using the Java library with Beam.
Using the PubSubLite IO, we get PCollection of SequencedMessage specifically: https://cloud.google.com/java/docs/reference/google-cloud-pubsublite/latest/com.google.cloud.pubsublite.proto.SequencedMessage
Now, from it I can get the data by doing something like:
message.getMessage().getData().toByteArray()
and then doing the normal conversion.
But for attributes, I cannot seem to get it correctly, just the value. In Go, I could do:
msg.Attributes["attrKey"]
but when I do:
message.getMessage().getAttributesMap().get("attrKey")
I am getting an Object which I cannot seem to convert to just string value of it. As far as I understand, it returns a Map<String, AttributeValues> and they all seem to be just wrapper over the internal protobuf. Also, Map is an interface so how do I get to the actual implementation to get the underlying value of each of the attribute.
The SequencedMessage attributes represent a multimap of string to bytes, not a map of string to string like in standard Pub/Sub. In the go client, by default the client will error if there are multiple values for a given key or if any of the values is not valid UTF-8, and thus presents a map[string]string interface.
When you call message.getMessage().getAttributesMap().get("attrKey"), you have a value of type AttributeValues which is a holder for a list of ByteStrings. To convert this to a single String, you would need to throw if the list is not of length 1, then call toStringUtf8 on the byte string element with index 0.
If you wish to interact with the standard Pub/Sub message format like you would in go, you can convert to this format by doing:
import org.apache.beam.sdk.io.gcp.pubsub.PubsubMessage;
import org.apache.beam.sdk.io.gcp.pubsublite.CloudPubsubTransforms;
PCollection<SequencedMessage> messages = ...
PCollection<PubsubMessage> transformed = messages.apply(CloudPubsubTransforms.toCloudPubsubMessages());

Is there a way to test events from the test fixture directly without using expectEvents?

Im trying to test an Aggregate and would like to assert the events outside of the fixture and perhaps even use Hamcrest to evaluate?
An example of using timestamps
fixture.given()
.when(new UserCreateCommand("1","test#bob.com"))
.expectEvents(new UserCreatedEvent("1","test#bob.com");
The fixture allows me to easily test equality, e.g. the command produces exactly this event, its not so easy if I wanted to say introduce a Timestamp of when the event was created for example
fixture.given()
.when(new UserCreateCommand("1","test#bob.com"))
.expectEvents(new UserCreatedEvent("1","test#bob.com", LocalDateTime.now());
This expectation will never work as the LocalDateTime.now() will never be precisely equal to the timestamp generated in the aggregate.
I could simply include the Timestamp in the command payload, but feel a preference to handle inside the Aggregate to ensure a consistent way of generating this timestamps.
Is there a way to retrieve the Event out of the fixture to assert independently of the fixture e.g.
UserCreatedEvent uce = fixture.given()
.when(new UserCreateCommand("1","test#bob.com"))
.extractEvent(UserCreatedEvent.class)
This would then allow me to use other assertion libraries also like hamcrest for example:
e.g.
assertThat(uce.getCreatedAt(), is(greaterThanOrEqualto(LocalDateTime.now().minusSeconds(1);
Reasonable question #vcetinick!
You should actually be able to use matchers with Axon's Aggregate Test Fixtures really. The result validation part of the AggregateTestFixture provides the expectEventsMatching(Matcher<? extends List<? super EventMessage<?>>> matcher) method. You can find the code for this here by the way.
On top of this Axon Framework provides a set of reasonable matchers you can use for messages in general, grouped under the utility class Matchers (which you can find here).
With all this in place, you should be able to do something like this:
#Test
void sampleTest() {
FixtureConfiguration<SampleAggregate> fixture =
new AggregateTestFixture<>(SampleAggregate.class);
fixture.givenNoPriorActivity()
.when(new UserCreateCommand("1","test#bob.com"))
.expectEventsMatching(
Matchers.exactSequenceOf(
Matchers.messageWithPayload(
Matchers.matches(payload -> {
// Your UserCreatedEvent validation
// disregarding the time stamp here
})
)
)
);
}
You can essentially pair any number of Matchers methods in their if you desire.
Hoping this answers your question #vcetinick!
Despite being an old post, for those stumbling upon the same issue, an alternative approach can be used by using
fixture = new AggregateTestFixture<>(YourAggregate.class);
fixture.registerFieldFilter(new IgnoreField(YourEvent.class, "date"));
In this example, YourEvent could be an event implementation class of a base class for all events containing a timestamp field date.
#NotNull(message = "The event date cannot be null")
#Past(message = "The event date cannot be in the future")
#JsonProperty(value = EVENT_DATE_TAG, required = true)
private ZonedDateTime date;
Using this approach, all calls to expectXXXX test-methods ignore the date field.

Accessing math functions with sqlite-net-pcl and Xamarin.Forms

When writing a C# console App, and using System.Data.SQLite, I am able to perform SQL commands such as:
string cosfun = string.Format("UPDATE test SET cosColumn = column1*cos(20));
However, when I try using a similar command in Xamarin.Forms, using the sqlite-net-pcl package, I get the followin error: SQLite.SQLiteException: 'no such function: cos'
I have found a similar question on SO (Custom SQLite functions in Xamarin.iOS). However, I didn't fully understand the response. I now have the following questions:
1) Can I make custom SQL functions using sqlite-net-pcl in Xamarin.Forms? If so, could someone please share a simple (but complete) example of how to do this?
2) Is there anyway for me to access the same math functions (pow, cos, sin, etc.) that I can access when writing console Apps in C#?
3) Is there another way to do this? For example, can I read columns from the database into a List, then perform the required math functions, and feed that back into the database? Would this be a terrible idea with a large database?
Thanks in advance,
Dustin
First is OK.
The SQLite-net PCL by Frank Kreuger is the one that Xamarin University uses in their XAM160 - Working with SQLite and Mobile Data class: https://university.xamarin.com/classes/track/cross-platform-design
Second is Ok.
You can find some documentation on how to get started on the Xamarin developer site: http://developer.xamarin.com/recipes/android/data/databases/sqlite/
Third answer is clear.
More Info:
You can refer to official document in here, Another similar discussion may be helpful for you this.
Correct me if I'm wrong, but what you're trying to do is essentially have two columns where one contains a set of data, and the other contains the result of a simple mathematical operation from the first column. From this you have two columns where one is dependent on the other, which means you are occupying double the necessary memory space. For a 100 entries, that's alright. For 1,000,000? Less so.
I personally thing you are better off not having cosColumn, and you should calculate the cosine when you read the data. For example:
// In your C# code...
public class MyData
{
public double Column1 { get; set; } = 0.0;
public double Cosine => Math.Cos(Column1);
}
In the above, the cosine value is never stored or created in neither C# or SQLite, but it is obtained only when needed. This makes it much more memory-friendly to the SQLite table, and it implements a better SQLite structure.
In the code above, the line:
public double Cosine => Math.Cos(Column1);
is exactly equivalent to:
public double Cosine
{
get
{
return Math.Cos(Column1);
}
}
There's no real difference between the two, and you save a lot of line-space. You can find more information on the => notation from this StackOverflow answer by Alex Booker.
Let's go through an example of implementing this structure. Suppose you have a database with 1 column with the name Column1, and you want to apply a Cosine function to this value and display it. Your code might look like:
// Read from database object of type MyData
MyData data = ReadOneValueFromDatabase<MyData>();
// Display values in a label
MyValueLabel.Text = "Database value: " + data.Column1.ToString();
MyCosineLabel.Text = "Cosine value: " + data.Cosine.ToString();
The object data will store the value of Column1 from the database in Column1, but not Cosine. The value of Cosine is only obtained when you call data.Cosine.

Can I pass an array to a function using the ... rest* construction?

I'm making multiple similar calls with similar results to one remote object. Because these calls are so similar and very changeable, I've been keeping the name of the remote method in a config file, and when I need to make the call I use getOperation() on the remote object, and call send() on the operation object. However, the requirements have changed so that not all of the calls will have the same number of parameters.
Because send uses ..., will I be able to continue using the same formation and pass an array, or will send() treat that as passing one argument of type array?
The Operation class also has an "arguments" property that you can use. That way you can prefill it before calling send(). The send() method then requires not extra arguments.
var operation:Operation = Operation(remoteObject.getOperation(methodName));
operation.arguments = parameters;
var token:AsyncToken = operation.send();
var responder:Responder = new Responder(resultHandler, faultHandler);
token.addResponder(responder);
you can use the ...rest
that will give you an array with a bunch of objects. I would recommend tat you make the first item [0] always the ID. This ID should identify either the sender or the type of object being passed. you can easily do a switch/case for each type of item. You could also do a more sophisticated way of dealing with this, but this should work.

index out of range exception when storing into asp.net session

I'm building a web app that to build a report, but there are too many arguments to give each one a name, and I want to save them indexed by numbers so I can handle them with loops later on throughout the application.
However, I'm getting an index out of range on the very first session item(0)...as I understand it, I don't have to instantiate a session myself and this should work right?
Session[0] = txtComplianceCaseID.Text;
Session[1] = ddlState.SelectedValue;
Session[2] = txtActingSupervisor.Text;
Session[3] = ddlRiskTolerance.SelectedValue;
etc...
The Session object is a string dictionary; you should store objects in it with string keys.
Writing Session[0] will get or set the first item in session state.
Since Session state starts empty, it throws an exception.
Instead, you should use strings, like this:
Session["Compliance ID"] = txtComplianceCaseID.Text;
Session["State"] = ddlState.SelectedValue;
Session["Supervisor"] = txtActingSupervisor.Text;
Session["Risk Tolerance"] = ddlRiskTolerance.SelectedValue;
You can also call the Add method.
Read more about Asp.net Session Object and how to fill it with information here

Resources