Passing variable to scenario in ODI 11G load plan not working - oracle-data-integrator

I have a trouble with passing variable value to ODI scenario. On property inspector for scenario step I check "overwrite" against a variable and then provide as a value #same_project.another_variable. At runtime exactly this string is passed to scenario though I expect it to be substituted by variable value.
Both variables (the one to be set and the one to provide value) are declared in Variables section of load plan.
What can be the reason for this? How this can be fixed?

Related

Does `instance` variable cause poor performance?

I used a state boolean variable didApiCalled to check whether the API gets called or not.
But I also wanted to use a instance variable for this usecase as instance variable didn't re-render. My colleague thinks this is a bad idea as this will cause some binding issue or it'll throw some error.

Oozie: pass parameter via separate file

I'm experimenting with the loop 'hack' to iterate the same workflow over a list of of values and I am trying to load that list at run-time.
The list contains a number of files that I would like to process and so this list will change every time.
In the example the value is passed via the job.properties file and I can also pass it in the workflow itself as a key/value pair but than the values are hard-coded in my workflow and I would like to prevent that (as the list will change every time).
I found a similar question:
OOZIE: properties defined in file referenced in global job-xml not visible in workflow.xml
and the answer there explains also my initial mistakes (parameters vs properties) where I tried to pass it via a global job.xml file (which is only for properties and not for parameters) but a good solution is not provided.
One solution would be to read the parameter from a file via a shell action and capturing the output but I think there could be a more elegant way of reading this parameter in my workflow?

Save to .settings file diffrence between 2 diffrent ways of saving

I was reading about the .settings file on msdn and I noticed they give 2 examples of how to set the value of a item in the settings. Now my question is what is the real diffrence between the 2 and when would you use one instead of the other, since to me they seem pretty mutch the same.
To Write and Persist User Settings at Run Time
Access the user setting and assign it a new value, as shown in the following example:
Properties.Settings.Default.myColor = Color.AliceBlue;
If you want to persist changes to user settings between application sessions, call the Save method, as shown in the following code:
Properties.Settings.Default.Save();
The first statement updates the value of the setting in memory. The second statement updates the persisted value in the user.config file on the disk. That second statement is required to get the value back when you restart the program.
It is very, very important to realize that these two statements must be separate and never be written close together in your code. Keeping them close is harakiri-code. Settings tend to implement unsubtle features in your code, making it operate differently. Which isn't always perfectly tested. What you strongly want to avoid is persisting a setting value that subsequently crashes your program.
That's the harakiri angle, if you saved that value then it is highly likely that the program will immediately crash again when the user restarts it. Or in other words, your program will never run correctly again.
The Save() call must be made when you have a reasonable guarantee that nothing bad happened when the new setting value was used. It belongs at the end of your Main() method. Only reached when the program terminated normally.

Is there a way to execute same scenario concurrently and reuse the variables?

I created several specific scenarios that sets a variables (see Image 1 below) and then calls PROCESS_RECORDS
I created a generic ODI scenario (PROCESS_RECORDS) that performs approx. 6 steps; this scenario uses variables that are set in the calling scenario.
I ran into issues when these scenarios would run concurrently; the variables would get overwritten and PROCESS_RECORDS would use the incorrect value.
Image 1: Example of a scenario calling PROCESS_RECORDS:
Image 2: PROCESS_RECORDS Scenario:
To correct, I made several copies of the variables (in Image 1). However this required me to create several copies of other variables, procedures, etc. in PROCESS_RECORDS. And now my "generic" and "reusable" scenario is no more. I thought that the variables would be created as local vars and not global vars.
Is there a way to execute same scenario concurrently and reuse the variables?
First, in your main package, in the additionnal variables header of StartScen property box, you must select a project, a variable and set the value of the variable starting with # and keep the variable's name :
Second, in your package called by main package, you have to put your variable and choose type "Declare Variable" :

SSRS Code Shared Variables and Simultaneous Report Execution

We have some SSRS reports that are failing when two of them are executed very close together.
I've found out that if two instances of an SSRS report run at the same time, any Code variables declared at the class level (not inside a function) can collide. I suspect this may be the cause of our report failures and I'm working up a potential fix.
The reason we're using the Code portion of SSRS at all is for things like custom group and page header calculation. The code is called from expressions in TextBoxes and returns what the current label should be. The code needs to maintain state to remember what the last header value was in order return it when unknown or to store the new header value for reuse.
Note: here are my resources for the variable collision problem:
The MSDN SSRS Forum:
Because this uses static variables, if two people run the report at the exact same
moment, there's a slim chance one will smash the other's variable state (In SQL 2000,
this could occasionally happen due to two users paginating through the same report at
the same time, not just due to exactly simultaneous executions). If you need to be 100%
certain to avoid this, you can make each of the shared variables a hash table based on
user ID (Globals!UserID).
Embedded Code in Reporting Services:
... if multiple users are executing the report with this code at the same time, both
reports will be changing the same Count field (that is why it is a shared field). You
don’t want to debug these sorts of interactions – stick to shared functions using only
local variables (variables passed ByVal or declared in the function body).
I guess the idea is that on the report generation server, the report is loaded and the Code module is a static class. If a second clients ask for the same report as another quickly enough, it connects to the same instance of that static class. (You're welcome to correct my description if I'm getting this wrong.)
So, I was proceeding with the idea of using a hash table to keep things isolated. I was planning on the hash key being an internal report parameter called InstanceID with default =Guid.NewGuid().ToString().
Part way through my research into this, though, I found that it is even more complicated because Hashtables aren't thread-safe, according to Maintaining State in Reporting Services.
That writer has code similar to what I was developing, only the whole thread-safe thing is completely outside my experience. It's going to take me hours to research all this and put together sensible code that I can be confident of and that performs well.
So before I go too much farther, I'm wondering if anyone else has already been down this path and could give me some advice. Here's the code I have so far:
Private Shared Data As New System.Collections.Hashtable()
Public Shared Function Initialize() As String
If Not Data.ContainsKey(Parameters!InstanceID.Value) Then
Data.Add(Parameters!InstanceID.Value, New System.Collections.Hashtable())
End If
LetValue("SomethingCount", 0)
Return ""
End Function
Private Shared Function GetValue(ByVal Name As String) As Object
Return Data.Item(Parameters!InstanceID.Value).Item(Name)
End Function
Private Shared Sub LetValue(ByVal Name As String, ByVal Value As Object)
Dim V As System.Collections.Hashtable = Data.Item(Parameters!InstanceID.Value)
If Not V.ContainsKey(Name) Then
V.Add(Name, Value)
Else
V.Item(Name) = Value
End If
End Sub
Public Shared Function SomethingCount() As Long
SomethingCount = GetValue("SomethingCount") + 1
LetValue("SomethingCount", SomethingCount)
End Function
My biggest concern here is thread safety. I might be able to figure out the rest of the questions below, but I am not experienced with this and I know it is an area that it is EASY to go wrong in. The link above uses the method Dim _sht as System.Collections.Hashtable = System.Collections.Hashtable.Synchronized(_hashtable). Is that best? What about Mutex? Semaphore? I have no experience in this.
I think the namespace System.Collections for Hashtable is correct, but I'm having trouble adding System.Collections as a reference in my report to try to cure my current error of "Could not load file or assembly 'System.Collections'". When I browse to add the reference, it's not an available component to select.
I just confirmed that I can call code from a parameter's default value expression, so I'll put my Initialize code there. I also just found out about the OnInit procedure, but this has its own gotchas to research and work around: the Parameters collection may not be referenced from the OnInit method during parameter initialization.
I'm unsure about declaring the Data variable as New, perhaps it should be only be instantiated in the initializer if not already done (but I worry about race conditions because of the delay between the check that it's empty and the instantiation of it).
I also have a question about the Shared keyword. Is it necessary in all cases? I get errors if I leave it off function declarations, but it appears to work when I leave it off the variable declaration. Testing multiple simultaneous report executions is difficult... Could someone explain what Shared means specifically in the context of SSRS Code?
Is there a better way to initialize variables? Should I provide a second parameter to the GetValue function which is the default value to use if it finds that the variable doesn't exist in the hashtable yet?
Is it better to have nested Hashtables as I chose in my implementation, or to concatenate my InstanceID with the variable name to have a flat hashtable?
I'd really appreciate guidance, ideas and/or critiques on any aspect of what I've presented here.
Thank you!
Erik
Your code looks fine. For thread safety only the root (shared) hashtable Data needs to be synchronised. If you want to avoid using your InstanceID you could use Globals.ExecutionTime and User.UserID concatenated.
Basically I think you just want to change to initialize like this:
Private Shared Data As System.Collections.Hashtable
If Data Is Nothing Then
Set Data = Hashtable.Synchronized(New System.Collections.Hashtable())
End If
The contained hashtables should only be used by one thread at a time anyway, but if in doubt, you could synchronize them too.

Resources