Get affected-rows value from mysql DB using Mule 3.5.x+ - mysql

On attempting to write to a table, I need to know if the row was updated (new row created or existing row updated) or not. I would have got this value from the affected-rows value.
Previously, the solution would have been to build a class like org.mule.transport.jdbc.sqlstrategy.SimpleUpdateSqlStatementStrategy and re-implement it to return the affected-rows value instead of the row itself.
However, it seems like the JDBC transport has been deprecated in favor of the Database connector, and I am finding it hard to track down the code or how to implement the functionality.
SOLUTION :
David's reply got me down the right track! Thanks David.
However, this problem was fixed in the mysql-connector-java in versions 5.1.27 and above.
So, the POM needed to be upgraded.
mysql
mysql-connector-java
5.1.27
I was able to achieve the right results using DBCP2 as follows:
<spring:beans>
<spring:bean id= "jdbcDataSource" class ="org.apache.commons.dbcp.BasicDataSource" name= "Bean">
<spring:property name= "driverClassName" value ="com.mysql.jdbc.Driver" />
<spring:property name= "username" value = "root"/>
<spring:property name= "password" value = "root"/>
<spring:property name="url" value="jdbc:mysql://localhost:3306/local1?useAffectedRows=true"/>
<!-- Following properties added for having auto reconnect mechanism-->
<spring:property name= "testOnBorrow" value = "true"/>
<spring:property name= "validationQuery" value = "select 1"/>
</spring:bean>
</spring:beans> <db:mysql-config name="MySQL_Configuration" dataSource-ref="jdbcDataSource" doc:name="MySQL_Configuration"/>

From the documentation:
target #[payload] The enricher expression used to enrich the current message with the result of the SQL processing.
This should allow you to define an expression that would tell Mule where to store the outcome of the update, which is the number of updated rows.
From the integration test suite:
<db:update config-ref="dbConfig"
target="#[header:OUTBOUND:updateCount]">
<db:parameterized-query>update PLANET set NAME='Mercury' where POSITION=4</db:parameterized-query>
</db:update>
This sets an outbound property named updateCount with the number of updated rows. I'd personally suggest to instead set a flow variable with #[flowVars['updateCount']], but it depends on your use case.

Related

Extract value from form and send to database service how a parameter (filter)

In my configuration, I try the next comand (BD mysql):
SELECT user, name, lastname FROM Cordloc
where user=<sql:param type="xs:string" select="/form/section-1/usuario"/>
This database service is conect to drowpdown, but when I incluye the sentence "where user=<sql:param type="xs:string" select="/form/section-1/usuario"/>",
this it's not working.
I try the show en drowdown name user, but filter with user login orbeon (in the table is same value "orbeon").
Please, can your help me with that.
Many thanks.
You can't use an XPath expression, such as /form/section-1/usuario, in the query. Instead, the value of the select attribute must be left empty (as mentioned in 1. Set a service parameter).
Instead, you "feed" the value to the service from the action. In the Actions Editor, under Set Database Service Parameters, you can say that the value from a given field should be used for a parameter of your SQL query.

how to get modified csv file while TestNG test suite is in progress

I am running a test suite in which testNG.xml looks like below:
<suite>
<test name="createFlow">
<classes>
<class name="createReservation">
</class>
</classes>
</test>
<test name="modifyFlow">
<classes>
<class name="modifyReservation">
</class>
</classes>
</test>
The parameters for creating the reservation are being taken from a reservation.csv. Once reservation gets created, reservation ID is stored in that csv,ie. it overrides the value of ID already present there, which is used for modifying that particular reservation, code of which is written in modifyReservation.java.
The problem i am facing is once i run the test suite, the modify flow doesn't fetch the recent reservation ID which is just created in reservation flow from csv, but it takes the ID which was earlier mentioned in the csv.
Please suggest what changes should i make so that in same suite, during the execution is going on, i am able to fetch the updated IDs.
In the file, you have read and write methods for reading/writing data in the csv file, use local variables in every method instead of global variables.
Create new object of FileInputStream and FileOutputStream in each and every method.
FileInputStream fis = new FileInputStream(csvFilePath);
Hope it will work
This is a perfect reason why databases were developed.
Create a new MongoDB or MySQL DB first.
Then create tables and columns based on your data needs.
Write a select query to get data from those tables.
You will avoid all sorts of permissions, locking, refresh etc issues by using databases.

Entity Framework - Stored Procedure with Multiple results sets - no rows return

so, i was trying to implement a stored procedure with multiple results sets in entity framework.
it all seemed to be too easy.
but, i am not getting any rows for my results sets (even though, it seems i do get the result sets themselves back).
What i have done:
created the stored procedure which returns 3 result sets
Created the complex type that represents the return values
manually edited the edmx file as per Stored Procedures with Multiple Result Sets
Failed with 3 and tried the code version from the same page, still no rows back.
Reverted the code back to 3.
my edmx file (related content only):
<FunctionImport Name="getGlobalReport2">
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<Parameter Name="regions" Mode="In" Type="String" />
<Parameter Name="countries" Mode="In" Type="String" />
<Parameter Name="companySizes" Mode="In" Type="String" />
<Parameter Name="products" Mode="In" Type="String" />
</FunctionImport>
<FunctionImportMapping FunctionImportName="getGlobalReport2" FunctionName="MTModel.Store.getGlobalReport2" >
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
</FunctionImportMapping>
my code:
var x = mtEntities.getGlobalReport2(regions, countries, companySizes, products);
Response.Write(x.Count());
var y = x.GetNextResult<GlobalReport2>();
Response.Write(y.Count());
var z = x.GetNextResult<GlobalReport2>();
What i have allready checked:
Checked that the server receives the request as per How can I view live MySQL queries?
Run the query i grabbed from the server and made sure it returns result sets and rows
Debug the app to see there are no Exceptions i missed on the way
There seems to be no issue with the call, or the app, except that no rows are returned.
Any suggestions?
EDIT:
as per your comments about the edmx being overwritten, that would happen only if i regenerate the model from the database, not if i update it.
i wouldn't expect anything else, since its regenerating the model.
Dont you think you should have some property defined for your complex types you have created ? For example:
<FunctionImportMapping FunctionImportName="GetGrades"
FunctionName="SchoolModel.Store.GetGrades" >
<ResultMapping>
<ComplexTypeMapping TypeName="SchoolModel.GradeInfo">
<ScalarProperty Name="EnrollmentID" ColumnName="enroll_id"/>
<ScalarProperty Name="CourseID" ColumnName="course_id"/>
<ScalarProperty Name="StudentID" ColumnName="student_id"/>
<ScalarProperty Name="Grade" ColumnName="grade"/>
</ComplexTypeMapping>
</ResultMapping>
</FunctionImportMapping>
Check this too
Also as rightly stated by Mike in the comment to your question, if you in future update your edmx file, if it's regenerated you're going to lose to customizations.

DbUnit: how to assert generated IDs

I need an idea/tip how to use DbUnit to assert IDs, generated by a database (e.g. MySQL's auto increment column). I have very simple case, which yet, at the moment, I find problematic:
2 tables: main and related. main.id column is an auto-increment. Related table has a foreign key to it: related.main_id -> main.id. In my test case my application does insert multiple entries into both tables, so the dataset looks similar to this:
<dataset>
<main id="???" comment="ABC" />
<main id="???" comment="DEF" />
<related id="..." main_id="???" comment="#1 related to ABC" />
<related id="..." main_id="???" comment="#2 related to ABC" />
<related id="..." main_id="???" comment="#3 related to DEF" />
<related id="..." main_id="???" comment="#4 related to DEF" />
</dataset>
As the order, how the inserts will be performed is unclear - I cannot simply clear/truncate the table before the test and use predefined IDs in advance (e.g. "ABC" entry will come at first so it gets ID 1 and "DEF" as 2nd - gets 2). If I write test such way - this will be wrong - with a bit of luck sometimes it may work and in other cases not.
Is there a clean way how test such cases? As I still want to assert that entries were created and linked properly in DB, not only that they exists (if I would simply ignore the auto-increment columns).
Based on the comments of the question, I am answering my own question, so this may help others, looking for similar solution.
After all we did skip asserting generated IDs, as they were not really interesting for us. What we actually did want to check is that the entries between main and related tables are "properly linked". To achieve this, in our unit test we did created the the dataset using query, joining both tables:
SELECT main.comment, related.comment AS related_comment
FROM main, related
WHERE main.id = related.main_id
Then we assert, that dataset produced by this query matches statically defined dataset:
<dataset>
<result comment="ABC" related_comment="#1 related to ABC" />
<result comment="ABC" related_comment="#2 related to ABC" />
<result comment="DEF" related_comment="#3 related to DEF" />
<result comment="DEF" related_comment="#4 related to DEF" />
</dataset>
When the datasets are matching, we can assume, that entries were "linked properly".
Maybe you let dbunit sort your table main by id and table related by id automatically. Since the absolute number of rows are known in advantage this should solve your problem.
DBUnit allows sorting with org.dbunit.dataset.SortedTable.SortedTable which needs a table an a list of colums which should be sorted. JavaDoc of SortedTable

How to get the identity of the user who ran a report?

When executing a report in MSCRM 2011, you have two options for the data sources : either SQL or Fetch.
In SSRS execution logs, the user who ran the report is always the service account.
When using fetch, in the report execution log, there is a parameter CRM_FullName containing the full name of the user who ran the report.
When using SQL source, there is no CRM_FullName parameter. How can I know who ran the report? There must be a way to know, since the Filtered views know who I am.
There is actually no way to find this information. When you create a report for MSCRM, you use a connector called "MSCRM Data Connector". This can be seen in the AdditionnalInfo column of the ExecutionLogs3 view on the SSRS instance. When using this connector and trying to show a report, you will get prompted for username and password. That's where things get interesting.
The report is not actually expecting a username/password! In fact, it expects to receive the systemuserid (guid) as username and the organizationid (guid) as password. It then search in the MSCRM_CONFIG database for the organization database settings. Then, it goes into the organization database and simply do a set context_info SYSTEMUSERID. Finally, the filteredviews are calling a function named '[dbo].[fn_FindUserGuid]' that retrieves the context_info. That is how the filtered views are properly working, while connected as the service account.
As you might have expected, we can't know the user who ran the report because the username and password prompts in SSRS are never logged anywhere (for security matters, perhaps).
The best option that I have found to log who ran a report is to actually create a stored procedure that will make a select statement on the filtered views (or any tables, as it is) and then log into a separate table the statement, the procedure parameters and the context_info(). Then, in SSRS I call that function instead of going to the filtered views directly.
Answer edited to include the getting the user fullname if sql source is used.
Register a parameter, UserID, with default value as
=User!UserID
Use the following query in your dataset
SELECT DomainName, FullName
FROM SystemUserBase
WHERE (DomainName = #UserID)
Then use
=Fields!FullName.Value
in your report.
In the CRM the user data is stored in the SystemUserBase table, and the DomainName column is the actual Domain\Username stored in User!UserID of the report.
If you prefer using views, use FilteredSystemUser view instead of SystemUserBase table.
For fetchxml try the following:
The operator operator='eq-userid' means equal to the current user.
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
<entity name='team'>
<attribute name='name' />
<attribute name='businessunitid' />
<attribute name='teamid' />
<order attribute='name' descending='false' />
<link-entity name='teammembership' from='teamid' to='teamid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='user'>
<attribute name='fullname' />
<attribute name='systemuserid'/>
<filter type='and'>
<condition attribute='systemuserid' operator='eq-userid' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>
Then in your report you can use the following code in an expression to get the users fullname
=First(Fields!user_fullname.Value, "GetUserData")
where the dataset is called GetUserData
Will the user login name suffice? i.e. can you just use something like
="Generated by " & User!UserID ?