I have a bunch of unit tests that run camel routes with code like
// setup code here...
String route = "direct:someroute";
try (CamelContext context = new DefaultCamelContext()) {
Object response = runCamelRoute(context, route, ci);
checkResponse(route, response);
}
but this route expects an exchange property to be set before it gets here - how can I set it? CamelContext has a whole lot of methods but I can't seem to find something like:
CamelRoute cr = context.getRoute(route);
cr.getExchange().setProperty("propertyName", "propetyValue");
Here is my camel run method for unit testing, with a bit of extra code for setting up an Oracle connection, etc.
protected Object runCamelRoute(CamelContext context, String route, Object message) throws Exception {
context.addRoutes(new MyRouteBuilder() {
});
setupRegistry(context);
context.start();
FluentProducerTemplate template = context.createFluentProducerTemplate();
template.withBody(message)
.withHeader("hello", "goodbye")
.withProcessor(e -> e.setProperty("propertyName", "propertyValue")) // fail use header instead
.to(route);
try {
Future<Object> future = template.asyncRequest();
return future.get();
}
catch(Exception ex) {
System.out.println(route + " " + ex.getClass().getCanonicleName() + " " + ex.getMessage());
throw ex;
}
finally {
template.stop();
context.stop();
}
}
private void setupRegistry(CamelContext context) {
DataSource ds = DataSourceHelper.createConnectionPoolDev();
context.getRegistry().bind("dataSource", ds);
context.getRegistry().bind("Transformer", new Transformer());
}
public static OracleDataSource createConnectionPoolDev() {
try {
OracleDataSource ds = new OracleDataSource();
ds.setConnectionCacheName("oraCache");
ds.setURL("jdbc:oracle:thin:#//cluster:1521/server.domain.ca");
ds.setUser("user");
ds.setPassword("pass");
return ds;
}
catch (Exception ex) {
logger.error("Failed to create connection to the database " + ex.getMessage());
}
return null;
}
Something like this may be ?
context.createFluentProducerTemplate()
.withBody(...)
.withHeader(..., ...)
.withProcessor( e -> e.setProperty(propertyName, propertyValue) )
.to("direct:someroute")
.send();
Related
I have client like this :
import org.basex.api.client.ClientSession;
#Slf4j
#Component(value = "baseXAircrewClient")
#DependsOn(value = "baseXAircrewServer")
public class BaseXAircrewClient {
#Value("${basex.server.host}")
private String basexServerHost;
#Value("${basex.server.port}")
private int basexServerPort;
#Value("${basex.admin.password}")
private String basexAdminPassword;
#Getter
private ClientSession session;
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
this.session = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
}
}
It is a singleton injected in a service which run mulitple queries like this :
Query query = client.getSession().query(finalQuery);
return query.execute();
All threads query and share the same session.
With a single thread all is fine but with multiple thread I get some random (and weird) error, like the result of a query to as a result of another.
I feel that I should put a synchronized(){} arround query.execute() or open and close session for each query, or create a pool of session.
But I don't find any documentation how the use the session in parrallel.
Is this implementation fine for multithreading (and my issue is comming from something else) or should I do it differently ?
I ended creating a simple pool by adding removing the client from a ArrayBlockingQueue and it is working nicely :
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
final int poolSize = 5;
this.resources = new ArrayBlockingQueue < ClientSession > (poolSize) {
{
for (int i = 0; i < poolSize; i++) {
add(initClient());
}
}
};
}
private ClientSession initClient() throws IOException {
ClientSession clientSession = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
return clientSession;
}
public Query query(String finalQuery) throws IOException {
ClientSession clientSession = null;
try {
clientSession = resources.take();
Query result = clientSession.query(finalQuery);
return result;
} catch (InterruptedException e) {
log.error("Error during query execution: " + e.getMessage(), e);
} finally {
if (clientSession != null) {
try {
resources.put(clientSession);
} catch (InterruptedException e) {
log.error("Error adding to pool : " + e.getMessage(), e);
}
}
}
return null;
}
I found the following error in a Mule 4 components. How can I report this issue to Mulesoft?
Mule 4 XML Module 1.2.3 introduced a bug that causes the wrong Mule error to be raised in the module.
When validating an invalid XML payload (non-xml string, "XML" with unclosed or unpaired tags, etc) version 1.2.2 of the component would raise mule error XML-MODULE:INVALID_INPUT_XML, but with version 1.2.3 of the component the error is now XML-MODULE:TRANSFORMATION.
The problem seems to be that version 1.2.3 of the module removed the call to XMLUtils.toDOMNode, which was used to do an initial validation of the message and threw exception of class InvalidInputXmlException when processing an invalid XML.
XML module : 1.2.2
public class SchemaValidatorOperation extends PooledTransformerOperation<SchemaValidatorOperation.SchemaKey, Validator> {
private LSResourceResolver resourceResolver = (LSResourceResolver)new MuleResourceResolver();
#Validator
#Execution(ExecutionType.CPU_INTENSIVE)
#Throws({SchemaValidatorErrorTypeProvider.class})
public void validateSchema(#Path(type = PathModel.Type.FILE, acceptedFileExtensions = {"xsd"}) String schemas, #Optional(defaultValue = "W3C") SchemaLanguage schemaLanguage, #Content(primary = true) InputStream content, #Config XmlModule config) {
Node node = XMLUtils.toDOMNode(content, this.documentBuilderFactory);
withTransformer(new SchemaKey(schemas, schemaLanguage.getLanguageUri(), this.expandEntities), validator -> {
validator.setResourceResolver(this.resourceResolver);
final List<SchemaViolation> errors = new LinkedList<>();
validator.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException exception) {}
public void error(SAXParseException exception) {
trackError(exception);
}
public void fatalError(SAXParseException exception) {
trackError(exception);
}
private void trackError(SAXParseException exception) {
errors.add(new SchemaViolation(exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage()));
}
});
try {
validator.validate(new DOMSource(node));
} catch (SAXParseException e) {
throw new TransformationException("Failed to validate schema. " + e.getMessage(), e);
} catch (IOException e) {
throw new InvalidInputXmlException("Could not validate schema because the input was not valid XML. " + e.getMessage(), e);
}
if (!errors.isEmpty())
throw new SchemaValidationException("Input XML was not compliant with the schema. Check this error's Mule message for the list of problems (e.g: #[error.errorMessage.payload[0].description)", errors);
return null;
});
}
XML module : 1.2.3
public class SchemaValidatorOperation extends PooledTransformerOperation<SchemaValidatorOperation.SchemaKey, Validator> {
private LSResourceResolver resourceResolver = (LSResourceResolver)new MuleResourceResolver();
#Validator
#Execution(ExecutionType.CPU_INTENSIVE)
#Throws({SchemaValidatorErrorTypeProvider.class})
public void validateSchema(#Path(type = PathModel.Type.FILE, acceptedFileExtensions = {"xsd"}) String schemas, #Optional(defaultValue = "W3C") SchemaLanguage schemaLanguage, #Content(primary = true) InputStream content, #Config XmlModule config) {
withTransformer(new SchemaKey(schemas, schemaLanguage.getLanguageUri(), this.expandEntities), validator -> {
validator.setResourceResolver(this.resourceResolver);
final List<SchemaViolation> errors = new LinkedList<>();
validator.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException exception) {}
public void error(SAXParseException exception) {
trackError(exception);
}
public void fatalError(SAXParseException exception) {
trackError(exception);
}
private void trackError(SAXParseException exception) {
errors.add(new SchemaViolation(exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage()));
}
});
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setFeature("http://xml.org/sax/features/external-general-entities", this.expandEntities.isAcceptExternalEntities());
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", this.expandEntities.isAcceptExternalEntities());
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !this.expandEntities.isExpandInternalEntities());
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", this.expandEntities.isExpandInternalEntities());
validator.validate(new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(content)));
} catch (SAXParseException e) {
throw new TransformationException("Failed to validate schema. " + e.getMessage(), e);
} catch (IOException e) {
throw new InvalidInputXmlException("Could not validate schema because the input was not valid XML. " + e.getMessage(), e);
}
if (!errors.isEmpty())
throw new SchemaValidationException("Input XML was not compliant with the schema. Check this error's Mule message for the list of problems (e.g: #[error.errorMessage.payload[0].description)", errors);
return null;
});
}
Not that XMLUtils.toDOMNode was perfect since it catched any Exception, but at least it was useful to detect instances when trying to validate an incorrect xml.
XMLUtils.toDOMNode
public class XMLUtils {
public static Node toDOMNode(InputStream src, DocumentBuilderFactory factory) {
return toDOMNode(src, factory, null);
}
public static Node toDOMNode(InputStream src, DocumentBuilderFactory factory, EntityResolver entityResolver) {
try {
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
if (entityResolver != null)
documentBuilder.setEntityResolver(entityResolver);
return documentBuilder.parse(src);
} catch (Exception e) {
throw new InvalidInputXmlException("Cannot parse input XML because it is invalid.", e);
}
}
}
For open source components of Mule like the XML Module you can open a JIRA ticket in MuleSoft open tracker: https://www.mulesoft.org/jira/projects/MULE. The sources for the XML module are at https://github.com/mulesoft/mule-xml-module so you could attach a push request to the ticket if you create one.
If you are a current customer of MuleSoft you can engage their Support directly.
I am using extent reportversion 4 and want one .html report after executing of all the testcases but it creates two html reports for executing the 3 methods in testclass
In the testclass, I have writteh code like that #beforemethod will execute before executing each testcase, followed by executing the testcase & in #aftermethod it will flush the repot to generate Html report and afterthat using #afterclass annotations to quit the driver**
**Testclass:**
public class HomePageTest extends BaseClass {
HomePage homePage;
public HomePageTest() {
super();
}
#BeforeMethod
#Parameters({ "platformName", "url", "udid" })
public void setUpHomePageClass(String platformName, String url, String udid) throws Exception {
try {
BaseClass baseClass = new BaseClass();
baseClass.initialize_driver(platformName, url, udid);
homePage = new HomePage(driver);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
#BeforeMethod
#Parameters({ "platformName", "url", "udid" })
public void setUpHomePageClass(String platformName, String url, String udid) throws Exception {
try {
BaseClass baseClass = new BaseClass();
baseClass.initialize_driver(platformName, url, udid);
homePage = new HomePage(driver);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Test(priority = 1, description = "Verify element i.e Top50 Txt on homepage test")
#Severity(SeverityLevel.NORMAL)
#Description("TestCase Description: Verify element i.e Top50 Txt on homepage")
public void verifyeElementsOnHomePageTest() throws Exception {
log.info("***Executing verifyElementsOnHomeScreenTest***");
logger = extent.createTest("Verify the elements on HomePage after redirecting to the splash screen");
log.info("wait for continue_button to be clickable");
TestUtil.waitForElementToBeClickable(By.id("continue_button"));
homePage.clickContinueBtnAfterSplashScreen();
log.info("Clicked on continue_button");
log.info("waitForUserNameToBeClickable - username");
boolean flag = homePage.validateTop50Txt();
Assert.assertTrue(flag);
log.info("Top50Txt isDisplayed");
log.info("verifyElementsonHomeScreenTest Ended");
}
#Test(priority = 2, description = "Swipe to next video test")
#Severity(SeverityLevel.NORMAL)
#Description("TestCase Description: Swipe from one video to another")
public void swipeToNxtVideoTest() throws InterruptedException {
try {
logger = extent.createTest("Swipe from one video to another & get the username ");
log.info("***Executing swipeToNxtVideoTest***");
log.info("waitForElementToPresenceOfElementLocated - username");
TestUtil.waitForElementToPresenceOfElementLocated(By.id("user_name"));
log.info("swipeverticalDown for nxt video");
TestUtil.swipeverticalDown();
log.info("swipeToNxtVideoTest Ended");
} catch (Exception e) {
e.printStackTrace();
log.error("Found Exception - swipeToNxtVideoTest");
}
}
/*
* #Test(priority = 3, retryAnalyzer =
* com.automation.listeners.RetryAnalyzer.class ) public void checkFailure() {
* Assert.assertEquals(true, false); System.out.println("failed");
*
* }
*/
#AfterMethod
public void getResult(ITestResult result) throws Exception {
if (result.getStatus() == ITestResult.FAILURE) {
logger.log(Status.FAIL,
MarkupHelper.createLabel(result.getName() + " - Test Case Failed", ExtentColor.RED));
logger.log(Status.FAIL,
MarkupHelper.createLabel(result.getThrowable() + " - Test Case Failed", ExtentColor.RED));
String screenshotPath = TestUtil.captureScreenAsBase64(driver, result.getName());
logger.fail("Snapshot below: " + logger.addScreenCaptureFromPath(screenshotPath));
} else if (result.getStatus() == ITestResult.SKIP) {
logger.log(Status.SKIP,
MarkupHelper.createLabel(result.getName() + " - Test Case Skipped", ExtentColor.ORANGE));
} else if (result.getStatus() == ITestResult.SUCCESS) {
logger.log(Status.PASS,
MarkupHelper.createLabel(result.getName() + " Test Case PASSED", ExtentColor.GREEN));
}
extent.flush();
}
#AfterClass
public void quitDriver() {
getDriver().quit();
}
Please do let me know where I have been lacking in code; I might have a intuitions that there is an issue in testng annotations in my code
Base Class:
DesiredCapabilities capabilities = new DesiredCapabilities();
public void setDriver(AppiumDriver<MobileElement> driver) {
tdriver.set(driver);
}
public static synchronized AppiumDriver<MobileElement> getDriver() {
return tdriver.get();
}
public BaseClass() {
try {
prop = new Properties();
FileInputStream ip = new FileInputStream(
System.getProperty("user.dir") + "/src/main/java/com/automation/config/config.properties");
prop.load(ip);
// extend reports
Date date = new Date();
SimpleDateFormat dateFormatFolder = new SimpleDateFormat("dd_MMM_yyyy");
File ResultDir = new File(System.getProperty("user.dir") + File.separator + "/FrameworkReports/"
+ dateFormatFolder.format(date));
// Defining Directory/Folder Name
if (!ResultDir.exists()) { // Checks that Directory/Folder Doesn't Exists!
ResultDir.mkdir();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("dd_MMM_yyyy_hh_mm_ssaa");
htmlReporter = new ExtentHtmlReporter(
ResultDir + "/" + "Report" + " " + dateFormat.format(date) + " .html");
htmlReporter.config().setDocumentTitle("Automation Report");
htmlReporter.config().setReportName("YOVO AUTOMATION");
htmlReporter.config().setTheme(Theme.DARK);
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
extent.setSystemInfo("Host Name", "localhost");
extent.setSystemInfo("Environment", "Windows 7");
extent.setSystemInfo("User Name", "Abhishek Chauhan");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initialize_driver(String platformName, String url, String udid) throws Exception {
log = LogManager.getLogger(BaseClass.class);
BasicConfigurator.configure();
File appDir = new File("/src/main/resources/apk");
File app = new File(appDir, "yovoapp-release.apk");
mDirpath = System.getProperty("user.dir");
mApkfilepath = mDirpath + "/app/yovoapp-release.apk";
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, platformName);
capabilities.setCapability(MobileCapabilityType.UDID, udid);
switch (platformName) {
case "Android":
capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60);
capabilities.setCapability("appPackage", prop.getProperty("androidAppPackage"));
capabilities.setCapability("appActivity", prop.getProperty("androidAppActivity"));
capabilities.setCapability("app", mApkfilepath);
capabilities.setCapability("noReset", true);
driver = new AppiumDriver<MobileElement>(new URL(url), capabilities);
// tdriver.set(driver);
// return getDriver();
case "IOS":
File classpathRoot = new File(System.getProperty("user.dir"));
// File appDir = new File(classpathRoot, "/build/");
// File app = new File(appDir, "WordPress.app");
capabilities.setCapability("platformVersion", "9.2");
capabilities.setCapability("deviceName", "iPhone 6");
capabilities.setCapability("app", app.getAbsolutePath());
// driver = new IOSDriver<MobileElement>(new
// URL("http://127.0.0.1:4723/wd/hub"), caps);
break;
default:
throw new Exception("Invalid platform! - " + platformName);
}
setDriver(driver);
}
I want to execute a method periodically, this method get informations from database it show it into a label, I tried the following code :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//update information
miseAjour();
}
}, 0, 2000);
when i run the main program, the background service run also normaly but when the informations changes on db i get this exception:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
And this is the code of method miseAjour :
public void miseAjour(){
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
int nbrAderent = rs.getInt("nbrAderent");
rs.close();
stmt.close();
connect.commit();
connect.close();
main_nbrAdrTot.setText(nbrAderent + "");
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can Timer for this, but I would recommend to use the JavaFX provided API called as ScheduledService.
ScheduledService is made to execute the same Task at regular intervals and since it creates a Task internally, there are API which help you to bind the value to the UI controls.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
// Call the method and update the message
updateMessage(miseAjour());
return object; // Useful in case you want to return data, else null
}
};
}
};
service.setPeriod(Duration.seconds(10)); //Runs every 10 seconds
//bind the service message properties to your Label
label.textProperty().bind(service.messageProperty()); // or use your label -> main_nbrAdrTot
Inside the dbcall method miseAjour, return the value that you have fetched and you want to update the label with :
public String miseAjour(){
String nbrAderent = null;
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
return nbrAderent;
}
Finnaly i resolved the problem ,here is the code :
public class TimerServiceApp {
public void start() throws Exception {
TimerService service = new TimerService();
service.setPeriod(Duration.seconds(10));
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
main_nbrAdrTot.setText(t.getSource().getMessage());
}
});
service.start();
}
private class TimerService extends ScheduledService<Integer> {
private final StringProperty nbrTotAderent = new SimpleStringProperty();
public final void setTotalAderentNumber(String value ) {
nbrTotAderent.set(value);
}
public String getTotalAderentNumber() throws SQLException {
String nbrAderent = null;
ResultSet rs=null;
Statement stmt=null;
Connection connect=null;
try {
dbConnection db = new dbConnection();
connect = db.connectiondb();
connect.setAutoCommit(false);
stmt= connect.createStatement();
rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
System.out.println(" Total aderent number updated to :" + nbrAderent + " Aderents ");
return nbrAderent;
}
protected Task<Integer> createTask() {
return new Task<Integer>() {
protected Integer call() throws SQLException {
nbrTotAderent.setValue(getTotalAderentNumber());
updateMessage(getTotalAderentNumber());
return Integer.parseInt(getTotalAderentNumber());
}
};
}
}
} `
and i called this service by :
TimerServiceApp s = new TimerServiceApp();
s.start();
i dont know if the solution is optimised but it work :) thank you #ItachiUchiha i took the solution from yout answer in the following link
I'm developing a BlackBerry Application where I should send Text SMS from BlackBerry Device.
As I'm new to Blackberry, started few days back I'm unable to proceed.
Can anyone Help with providing code snippets for send SMS from BlackBerry Device or Simulator?
Thanks in Advance.
Suresh.
public static void sendSMS(final String no, final String msg) {
// try {
new Thread() {
public void run() {
boolean smsSuccess = false;
if (RadioInfo.getNetworkType() == RadioInfo.NETWORK_CDMA) {
DatagramConnection dc = null;
try {
dc = (DatagramConnection) Connector.open("sms://" + no);
byte[] data = msg.getBytes();
Datagram dg = dc.newDatagram(dc.getMaximumLength());
dg.setData(data, 0, data.length);
dc.send(dg);
// / send successfully
smsSuccess = true;
} catch (Exception e) {
System.out.println("Exception 1 : " + e.toString());
e.printStackTrace();
smsSuccess = false;
} finally {
try {
dc.close();
dc = null;
} catch (IOException e) {
System.out.println("Exception 2 : " + e.toString());
e.printStackTrace();
}
}
} else {
MessageConnection conn = null;
try {
conn = (MessageConnection) Connector
.open("sms://" + no);
TextMessage tmsg = (TextMessage) conn
.newMessage(MessageConnection.TEXT_MESSAGE);
tmsg.setAddress("sms://" + no);
tmsg.setPayloadText(msg);
conn.send(tmsg);
smsSuccess = true;
} catch (Exception e) {
smsSuccess = false;
System.out.println("Exception 3 : " + e.toString());
e.printStackTrace();
} finally {
try {
conn.close();
conn = null;
} catch (IOException e) {
System.out.println("Exception 4 : " + e.toString());
e.printStackTrace();
}
}
}
if(smsSuccess)
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
Dialog.alert("success");
}
});
}else
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
Dialog.alert("failure");
}
});
}
}
}.start();
}
Check out the the above code function .... to send SMS from Blackberry
You haven't specified what language you are developing in, but if you are developing in java and, if you are using Eclipse for your development with the Blackberry Java plugins, you will find a wealth of sample applications in the plugins folder hierarchy. The actual location will depend on where you have installed Eclipse, but e.g. on my machine they are at: C:\Program Files\Eclipse\eclipse 3.6.2 BlackBerry\plugins\net.rim.ejde.componentpack7.0.0_7.0.0.33\components\samples\com\rim\samples\device for the OS7 samples. Similar samples will exist for the different OS plugins you have installed.
There is a long standing sample in most OS sample sets called smsdemo which should give you all the code you need. Even if you are not developing in java, this sample should give you an indication of the path you need to take to fulfil your requirement.