Reading System Variable from Script Component - ssis

What is the best way to read system variables from Script Component.
Tried as below: Works fine when is User variable
base.PreExecute();
IDTSVariables100 variables = null;
VariableDispenser.LockForRead("System::ContainerStartTime");
VariableDispenser.GetVariables(out variables);
auditTimeStamp = Convert.ToDateTime(variables[1].Value);
System.Windows.Forms.MessageBox.Show(auditTimeStamp.ToString());
variables.Unlock();
when tried to read System variable throws following error:
Script Component has encountered an exception in user code:
Project name: SC_0bfc7da1c6fe4b83bc124b87eb4178e5
Exception from HRESULT: 0xC0010009
at Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSVariables100.get_Item(Object Index)
at ScriptMain.PreExecute()
at Microsoft.SqlServer.Dts.Pipeline.ScriptComponentHost.PreExecute()
any clues please.
Thanks

You have changed the index, from
Convert.ToDateTime(variables[1].Value);
to
Convert.ToDateTime(variables[0].Value);

Ok got this done as
#region Class Variables
int jobId;
DateTime auditTimeStamp;
IDTSVariables100 variables;
const string tableName = "ORGANISATION_PROVIDER";
#endregion
public override void PreExecute()
{
#region On PreExecute - Get the JOB ID passed - COMMON
base.PreExecute();
variables= null;
VariableDispenser.LockForWrite("System::ContainerStartTime");
VariableDispenser.GetVariables(out variables);
auditTimeStamp = Convert.ToDateTime(variables[0].Value);
variables.Unlock();
#endregion
}
This works fine..not sure what i have done wrong previously.

You could create a user variable that is evaluated as an expression that references the system variable. Something like this
#[System :: PackageName].

Related

Unable to mock URL class using PowerMockito/Mockito

I am trying to use PowerMockito to mock the creation of the java.net.URL class in my code that I'm testing. Basically, I want to prevent the real HTTP request from occurring and instead 1) check the data when the request is made and 2) supply my own test data back on a mocked response. This is what I'm trying:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class })
public class Test {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
...
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
...
}
The code that I want to test looks like this:
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
Earlier in my test scenario I mock the wlInvokeUrlString to match "MyURLString". I've also tried using various other forms of the whenNew line, trying to inject the mock. No matter what I try, it never intercepts the constructor. All I want to do is "catch" the call to openConnection() and have it return my mocked HTTP connection instead of the real one.
I have mocked other classes ahead of this one in the same script and these are working as expected. Either I need a second pair of eyes (probably true) or there is something unique about the URL class. I did notice that if I use "whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to "thenAnswer" I could get it to trigger. Only problem is I never get the URL call for my code. What I see is an invocation of the 3-argument constructor for URL.class with all nulls for the parameters. Could it be this class is from the Java runtime and is bootstrapped by the test runner? Any help is much appreciated.
It's a common mistake when use PowerMockito.whenNew.
Note that you must prepare the class creating the new instance of MyClass for test, not the MyClass itself. E.g. if the class doing new MyClass() is called X then you'd have to do #PrepareForTest(X.class) in order for whenNew to work
From Powermock wiki
So, you need a bit change your test and add to #PrepareForTesta class which create a new instance of URLlike:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class , ConnectionUser.class})
public class URLTest {
public class URLTest {
private ConnectionUser connectionUser;
#Before
public void setUp() throws Exception {
connectionUser = new ConnectionUser();
}
#Test
public void testName() throws Exception {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
connectionUser.open();
assertEquals(mockedConnection, connectionUser.getConnection());
}
}
where:
public class ConnectionUser {
private String wlInvokeUrlString = "MyURLString";
private HttpURLConnection connection;
public void open() throws IOException {
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
}
public HttpURLConnection getConnection() {
return connection;
}
}
I'm not sure the difference between .withParameterTypes(x) and .withArguments(x) but I believe you need to set it up as follows for your code to work. Give it a try and let me know if this doesn't help.
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(mockedURL);
The problem is that the arguments of the real call are not matching with the expected in your mock.
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL) will return mockedURL only the call is new URL("MyURLString").
If you change it to:
PowerMockito.whenNew( URL.class ).withParameterTypes( String.class )
.withArguments( org.mockito.Matchers.any( String.class ) ).thenReturn( mockedURL );
It will catch any string passed to the constructor URL(String) (even null) and return your mock.
When you tried
"whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to
"thenAnswer" I could get it to trigger. Only problem is I never get
the URL call for my code. What I see is an invocation of the
3-argument constructor for URL.class with all nulls for the
parameters.
PowerMock will try to mock all constructors (org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.InvokeStubMethod at line 122) then it calls the first one (with 3 arguments) and mock its answer. But the subsequent calls will return the already mocked one because you told it to mock for any arguments. That's why you see just one call with null, null, null in your Answer.

Assign values to ssis variable

I am trying to assgin a value to a variable in script component using C# but unable to do so. Can anyone please post the code or tell me what wrong below.
public override void PostExecute()
base.PostExecute();
IDTSVariables100 varCollection = null;
this.VariableDispenser.LockForWrite("User::Variable");
this.VariableDispenser.GetVariables(out varCollection);
varCollection["User::Variable"].Value = #"TESTING";
MessageBox.Show(Variables.MerchOrgName.ToString());
This example is very comprehensive. Most of the time the easier of the two methods is sufficient - especially if you are just starting.
http://microsoft-ssis.blogspot.com/2011/01/how-to-use-variables-in-script.html

SSIS Script Component runtime error

I got a valid issue when I run my package. It runs failed in my PC and success in anyone else.
The error is caused by Script Component (turned red), and it is in Post Execute phase, not the post execute in the script componet, but in the runtime of package. The error is:
Information: 0x40043008 at Data Flow Task, SSIS.Pipeline: Post Execute phase is beginning.
Error: 0xC0047062 at Data Flow Task, Script Component [263]: System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSVariables100'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{22992C1D-393D-48FB-9A9F-4E4C62441CCA}' failed due to the following error: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).
I guess the issue is related to variables, because when I remove all the code related to variables, the package run successfully. The code in script component:
private int scheduled550;
private int scheduled620;
private int scheduled720;
private int scheduled820;
public override void PreExecute()
{
base.PreExecute();
scheduled550 = Variables.Count550;
scheduled620 = Variables.Count620;
scheduled720 = Variables.Count720;
scheduled820 = Variables.Count820;
}
public override void PostExecute()
{
base.PostExecute();
}
Did anyone ever encounter the same issue? Can anyone tell me what will POST Execute phase do? Thanks
More info: I have tried to re-install SQL Server, but this is not help. And not all the script component with variables failed running in my SSIS (not in the same package with the error one)
All the tasks/containers in an SSIS have the same lifecycle. You can see some of this by watching the Event Handlers fire. In a script component, inside a Data Flow Task, is going to under go various steps. Part of that is Validation (this contract says I should have a column from this table that is an integer type- can I connect, does it exist, is it the right type, etc).
After validation, tasks will have setup and tear down steps to perform. Since you appear to be working with SSIS Variables in your script, part of that pre/post execute time is spent allowing the translation of Variable (SSIS) to variable (.net) and back again.
Until I see the specific code in your PostExecute method that was causing the failure, I can't state what the code issue might have been.
I cannot recreate your issue. While this is the 2012 release of Integration Services, the Script Component as you are using it will behave the same. I did not send my output to Excel but that should not matter given it's the Script that is failing.
My Script component. I have selected my Variable, User::Count550 as a ReadOnly variable in the menu before editing my code.
public class ScriptMain : UserComponent
{
private int scheduled550;
public override void PreExecute()
{
base.PreExecute();
this.scheduled550 = Variables.Count550;
}
public override void PostExecute()
{
base.PostExecute();
//this.Variables.Count550 = scheduled550;
//this.VariableDispenser.LockForWrite("Count550");
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (true)
{
this.scheduled550++;
}
}
}

Custom Task : TaskHost parameters persistence

I am currently developing a custom task and I'm stuck on a problem.
My Custom Task consists of three files:
MBTask that contains the class that implements the interface "Task"
MBTaskUI that implements the interface "IDtsTaskUI"
MBForm which is a Form.
In MBTaskUI on the Initialize() function i reveive the TaskHost object and save it in a variable. And then in the GetView() function o send this TaskHost to my Form builder
public void Initialize(TaskHost taskHost, IServiceProvider serviceProvider)
{
this.taskHost = taskHost;
IDtsConnectionService cs = serviceProvider.GetService
(typeof(IDtsConnectionService)) as IDtsConnectionService;
this.connections = cs.GetConnections();
}
public ContainerControl GetView()
{
return new MBForm(this.taskHost, this.connections);
}
It work great and i can use this TaskHost in my Form to get parameters when i load the Form and save them when I close it.
String script_tmp = (String)th.Properties["myScript"].GetValue(th);
SqlConnection conn_tmp = (SqlConnection)th.Properties["myConnection"].GetValue(th);
th.Properties["myScript"].SetValue(th, myScript);
th.Properties["myConnection"].SetValue(th, myConnectionTarget);
And so, when i re-open my Task Editor, i use the parameters i received to initialize some objects.
But, and here is my problem, in my MBTask class, i have a Validate() function which verify the parameters (myConnection and myScript). and these parameters are always null (also after I normally initialized it by using the MBForm and the close function.
So, what I don't understand is why my parameters were not instanced ?
Isn't it the job of "th.Properties["myScript"].SetValue(th, myScript);" ?
myScript and myConnection are declared public in my MBTask.
public class MBTask : Task
{
public SqlConnection myConnection { get; set; }
public String myScript { get; set; }
I know these parameters are saved because i can get them back when i re-open the editor. So why are they null when I do the Validate() ?
Do I have to add a link to the TaskHost from the MBTaskUI and the one from the MBTask ?
It seems that there is something i don't understand here ...
Thanks for your help,
Léo Lejeune.
I fond the solution:
The system I implemented was correct. But if you want to use complex parameters (SQLConnection) you have to use XML saving.
So, to use the default saving parameter of the task, only use simple objects like String and Integer.
And the Validate function can't use parameters because they are not yet instanced and so they are null.

How to mock a method in PowerMock?

I'm using PowerMock 1.4.12 and JUnit 4.8.1. I'm having a problem getting a method to return the data I want it to. I have
#Before
public void setUp() throws Exception
{
...
userService = createMock(UserService.class);
loginController.setUserService(userService);
…
}
#Test
public final void testAuthenticateForLoggedInAdmin()
{
authorities.add(adminAuthority);
final User user = new User();
user.setUserName("userName");
user.setPassword("password");
user.setFirstName("firstName");
user.setMiddleName("middleName");
user.setLastName("lastName");
user.setUrl("localhost");
user.setId("id1");
final TestsubcoAuthenticationUser principal = new TestsubcoAuthenticationUser(user.getUserName(),
user.getPassword(),
true,
true,
true,
true,
authorities,
user.getFirstName(),
user.getLastName(),
user.getMiddleName(),
user.getUrl(),
user.getId(),
null,
null,
null);
authentication = new UsernamePasswordAuthenticationToken(principal, new Object(), authorities);
securityContext.setAuthentication(authentication);
mockStatic(SecurityContextHolder.class);
expect(SecurityContextHolder.getContext()).andReturn(securityContext);
expect(userService.findByUsernameAndUrl(user.getUserName(), user.getUrl())).andReturn(user);
...
String result = loginController.authenticate();
but when my method in question gets called from within the controller,
final User user = userService.findByUsernameAndUrl(sbUser.getUsername(), sbUser.getUrl());
the return value is null instead of the object I specified. Any theories behind why this is or suggestions for troubleshooting further? I have verified through debugging that the String parameter values passed in the controller are the same as what I specify in the "expect" method.
It looks like you did not call replay on your mocks.
replay
but when my method in question gets called from within the controller,
I am not sure what your mean, method in question gets called from within the controller.
When you call the method ,your userService object should be the same object which you mocked. also check the argument value if same.
I you dont find this usefull, share more detail in what your trying to unit test here.