I am working with preparing a solution for one of my uscases.
My solution is something that might look like this in abstract.
My question here is, when the two main flows are calling the same sub-flow cuncurrently,
it is going to work without any issues ?
Also do I need to write the code as thread safe for all the classes that are being used as
custom components/trnasformers in the sub-flow ?
My abstract configuration looks as given below.
<flow name="mainflow_1" >
<inbound-endpoint/>
<transformer ....>
<component ....>
<flow-ref name="subflow_1"></flow-ref>
<transformer ....>
<component ...>
<outbound-endpoint ....>
</flow>
<flow name="mainflow_2" >
<inbound-endpoint type="request-response" />
<transformer ....>
<component ....>
<flow-ref name="subflow_1"></flow-ref>
<transformer ....>
<component ...>
</flow>
<sub-flow name="subflow_1" >
<transformer ....>
<component ....>
<outbound-endpoint call to some service >
<transformer ....>
<component ...>
</sub-flow>
Please guide me.
A sub-flow acts like a macro: execution wise, it's as if the elements of the sub-flow were copied in the calling flow.
Thus it's the threading behaviour of the calling flow that will determine the threading behaviour of the sub-flow.
Whether they're used in sub-flows or main flows, you should write your component classes to be thread safe if you use singleton instances of them (the common use case). If you use prototype instances (one instance created per request) or pooled instances (limited number of instances, bottlenecks the threads), your component classes can be thread unsafe.
As a rule of thumb, strive for thread-safe stateless component classes as much as you can to save you potential optimization pain down the road.
Related
I have a message-enricher , inside that I have a call to data base to get sequence value. Here is the component of my flow
<enricher doc:name="Enrich Flow Variable">
<db:select config-ref="LocalhostPostgres" doc:name="Database">
<db:parameterized-query><![CDATA[Select (nextval('batch_id_seq'))]]></db:parameterized-query>
</db:select>
<enrich source="#[payload[0].nextval]" target="#[flowVars.flow_batch_id]" />
<enrich source="#['INPUT_CSV']" target="#[flowVars.flow_source_name]" />
</enricher>
what I want,, in my unit testing I want to mock it so that I can pass constant values to my flow_batch_id.
Is there any way to do it?. Please help me.
I wouldn't mock the enricher. Instead I would mock the db:select to return a sample result. You can either mock the db:select operation, or move the db:select to a sub-flow/private flow and mock that instead. Take a look at the munit mock documentation: https://docs.mulesoft.com/munit/v/1.1.1/mock-message-processor
I want to make a decision in a Mulesoft flow, and have looked at the Choice Flow Control. My problem, is that I want to do something if the condition is true, and nothing if it is false, something like:
if (condition == true)
do some work
or, in probably incorrect xml:
<choice doc:name="call a subflow if the test is true">
<when expression="#[flowVars.someVariable == True]">
<flow-ref name="doSomething" doc:name="do another thing"/>
</when>
</choice>
no else clause, and no default flow. How is this implemented in a Mulesoft flow?
I could cheat, and throw a logging call into a default flow, but I would prefer not to.
Unfortunately there is no simple 'if' processor in Mule. Choice with a dummy otherwise route or filters are the way to go for now.
There is a good discussion on this here: https://www.mulesoft.org/jira/browse/MULE-6129. THis has further links to possible enhancements such as an if/detour router.
Mule 4 UPDATE
In mule 4, you can now define a choice router with no need for an otherwise route. And filters no longer exist
You can get close with an async or enricher scope and a filter. It's not as elegant as a true <if> processor (or a standalone <when>), but you don't need a wasted <logger> to satisfy the <otherwise>.
Async method (when you don't need the payload afterwards):
<async>
<expression-filter expression="#[payload == 'red']" />
<logger category="com.box.integration.experiment" message="That's my favorite color!" level="INFO" />
</async>
Enricher method (when you do):
<enricher target="#[variable:colorName]">
<processor-chain>
<expression-filter expression="#[payload == 'red']" />
<set-payload value="vermillion" />
</processor-chain>
</enricher>
In a mule flow, when using a message router without setting a Processor in the section, and the MuleMessage does not match any of the clauses, an exception is thrown. To achieve a conditional behavior currently mule requires to set a dummy processor on the otherwise clause. One usability improvement would be letting the message be processed by the remaining part of the flow if no clause was matched and no processor provided
https://www.mulesoft.org/jira/browse/MULE-6129
I need several profiles for deployment. In the Maven POM I have defined a profile "dev" and a property "theHost" (as localhost):
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault> <!-- use dev profile by default -->
</activation>
<build>
</build>
<properties>
<theHost>localhost</theHost>
</properties>
</profile>
...
I have activated filterDeploymentDescriptor on the maven-ejb-plugin in order to tell it to filter (substitute) values in ejb-jar.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
--> <filterDeploymentDescriptor>true</filterDeploymentDescriptor>
</configuration>
</plugin
Finally, in ejb-jar.xml I refer to ${theHost} to obtain the desired profile-specific value for the #Resource attribute "host":
<session>
<ejb-name>MongoDao</ejb-name>
<ejb-class>com.coolcorp.MongoDao</ejb-class>
<session-type>Stateless</session-type>
<env-entry>
<env-entry-name>host</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>${theHost}</env-entry-value>
</env-entry>
...
This all works great with a regular Maven build. But when I run an EJB unit test using the Embedded Enterprise Bean Container of GlassFish [EJBContainer.createEJBContainer()], the maven-ejb-plugin seems to ignore filterDeploymentDescriptor=true. The EJB sees "${theHost}" instead of "localhost" although I run maven with the same "dev" profile.
mvn.bat -Pdev test
Does anybody have an idea why the substitution does not work when running a unit test? Is there something more I have to define especially for the unit test so that filtering of ejb-jar.xml occurs? Or a better approach to unit testing EJBs if different profiles exist?
Ideally, you would be able to specify an external "binding" for the env-entry. I know that's possible to do with WebSphere Application Server (via EnvEntry.Value properties), but I don't know if it's possible with Glassfish.
As a workaround, you could declare the env-entry for injection, and then check in PostConstruct whether any value was injected by the container (i.e., don't specify env-entry-value until you're deploying into the server). If you're using JNDI only, you can do the same thing with try/catch(NameNotFoundException).
#Resource(name="host")
private String host;
#PostConstruct
public void postConstruct() {
if (host == null) {
// Not configured at deployment time.
host = System.getProperty("test.host");
}
}
Workaround based on bkail's suggestion: Set a system property only for unit tests and discover it in postConstruct:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14.1</version>
<configuration>
<skip>false</skip>
<argLine>-Xmx1g -XX:MaxPermSize=128m</argLine>
<reuseForks>false</reuseForks> <!-- with reuse the EJB timer service would fail -->
<systemPropertyVariables>
<is.unittest>true</is.unittest>
</systemPropertyVariables>
</configuration>
</plugin>
And then in the Java method annotated with #PostConstruct:
// Override values that were not substituted in ejb-jar.xml
if (Boolean.getBoolean("is.unittest")) {
host = "localhost";
port = "27017";
authenticationRequired = false;
}
Issue: "The CurrentThread needs to have it's ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer."
First of all i have read all the solutions to the problems above and none works for me.May be i am missing something. I have tried adding Execution Thread entry into my app.config, also tried setting STAThread attribute and i am still facing the same exception as stated above.
Tools: Visual Studio 2010, Watin 2.1, c#
Scenario: Trying to run a unit test [watin script in c#] from a web application upon a button click. But the above exception is thrown when the script is about to launch IE on the following line :
IE mybrowser = new IE ("SomeURL here");
Any Thoughts ?
Got it from a friend. We actually dont have to add any app.config entry. Just start the thread in a single state. In my case, i wrote the following code in my button click handler:
System.Threading.Thread th = new Thread(new ThreadStart(Test));
th.SetApartmentState(ApartmentState.STA);
th.Start();
th.Join();
and i moved the call to unit test in the private. TEST method as follows:
private void Test()
{
var som = new Project.ClassName();
som.MethodToExecute();
}
What does your App.Config look like?
<NUnit>
<TestRunner>
<!-- Valid values are STA,MTA. Others ignored. -->
<add key="ApartmentState" value="STA"/>
</TestRunner>
</NUnit>
The above works for me on Win7, IE9 (32bit), and Watin2.1. It also works on WinXP, IE8, WatiN 2.1. I'm 99% sure it worked just fine on previous versions of WatiN as well. No other ApartmentState changes were needed.
Simply add [assembly: RequiresSTA] at the top of your file or at the entry point of your project.
I had already done the app.config changes
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="NUnit">
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler" />
</sectionGroup>
</configSections>
<NUnit>
<TestRunner>
<add key="ApartmentState" value="STA" />
</TestRunner>
</NUnit>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.3.13283" newVersion="2.6.3.13283" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
but no dice. I opened AssemblyInfo and added
[assembly: RequiresSTA]
and suddenly, the universe began to function properly again.
When I switch off haltonfailure or haltonerror in my jmunit tests like this:
<jmunit haltonerror="false" haltonfailure="false" failureproperty="testfailure">
<formatter type="xml" />
<classpath>
<path path="${jar_location}" />
<path path="${build}" />
</classpath>
<!-- Add -->
<test name="com.example.tests.Test1" todir="${reports}" />
<test name="com.example.tests.Test2" todir="${reports}" />
<test name="com.example.tests.Etc" todir="${reports}" />
</jmunit >
The build succeeds even when some tests failed. If I turn the halts on, then of course it halts immediately upon the first failure. The behaviour I want is that all tests are executed regardless of how many of them fail, but if ANY of them failed then the build won't be successful. The reason I want this is so that the reports can correctly show how many passes and failures, and which tests are failing.
How do I achieve this?
and/or
Is my thinking that I want all of the tests to be run flawed?
Easy peasy:
You need to add the command
<fail message="Something went wrong. Please check the test results." if="testfailure" />
to the target that contains your jmunit command after the jmunit command itself.
This way, the jmunit task will set the variable testfailure when one of the tests fails and the command fail will make the build unsuccessful if that property is set.
Hope that helps.