quartz scheduling in spring 3 with batch file - spring-mvc

i have a batch(backup.bat)file.in that i have written a command to create a backup of database
which is
<
set path=%path%;C:\Program files\MySQL\MySQL Server 5.1\bin;
mysqldump -u `root` -padmin -B jewellery > backup\jewellery.sql
exit
>
i have created a controller to call this batch file.
that is given below
<
public class JobScheduleController extends QuartzJobBean {
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
// check FTP
try {
Runtime rt = Runtime.getRuntime();
rt.exec("cmd.exe /c start Backup.bat");
.....
.....
......
catch(Exception ex){
ex.printStackTrace();
}
}
}
>
even i have given the mapping in bean.xml that is given below
!-- Start Job Schedule for Application Backup Controllers-->
<bean name="jobScheduleController" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.jewellery.web.JobScheduleController" />
</bean>
<bean id="cronjobScheduleController" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobScheduleController" />
<!-- run at 11 am (0 0 11 ? * *") (Seconds,Minutes,Hours,Day-of-Month,Month,Day-of-Week) -->
<property name="cronExpression" value="0 0 11 ? * *" />
</bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronjobScheduleController" />
</list>
</property>
</bean>
the problem is as per the given time the controller shuld search and invoke the batch file to execute.but it says the batch file not found.
where shuld i place the batch file .
the same code was running succussfully in spring 2.0,nw i have migrated to spring 3.
where shuld i place my batch file.?
i am using eclipse indigo...?and one more thing is this the best way to do it or some other way is also there..if there kindly let me knw.

Just set Backup.bat in your environment path variable

Related

Workaround for Qt Installer Framework not overwriting existing installation

This question is about version 2.0 of the Qt Installer Framework.
At this point, it is common knowledge for people using the Qt Installer Framework that, without customization, you simply can't overwrite an existing installation through your installer. This was apparently done to resolve some issues that occurred when this was done with the Qt framework.
However, for smaller, relatively simple projects, overwriting is perfectly fine and much more convenient than having to manually run the maintenance tool beforehand.
I am looking for a solution involving a custom UI + component script that adds a button to the target directory page that allows the user to either
Remove the specified directory if it exists, or
Run the maintenance tool in that directory.
It would be preferable to be able to run the maintenance tool in the target directory, having it automatically remove a given package, but I realize that that is asking for a little too much.
I have read answers to other questions on this site about solving the same problem, but none of the solutions work correctly. I would also like to mention that I have a component script up and running, but no custom UIs.
I finally found a workable solution.
You need three things to pull this off:
A component script,
A custom UI for the target directory page, and
A controller script that clicks through the uninstaller automatically.
I will now list verbatim what is working for me (with my project specific stuff). My component is called Atlas4500 Tuner
config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>Atlas4500 Tuner</Name>
<Version>1.0.0</Version>
<Title>Atlas4500 Tuner Installer</Title>
<Publisher>EF Johnson Technologies</Publisher>
<StartMenuDir>EF Johnson</StartMenuDir>
<TargetDir>C:\Program Files (x86)\EF Johnson\Atlas4500 Tuner</TargetDir>
</Installer>
packages/Atlas4500 Tuner/meta/package.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<DisplayName>Atlas4500Tuner</DisplayName>
<Description>Install the Atlas4500 Tuner</Description>
<Version>1.0.0</Version>
<ReleaseDate></ReleaseDate>
<Default>true</Default>
<Required>true</Required>
<Script>installscript.qs</Script>
<UserInterfaces>
<UserInterface>targetwidget.ui</UserInterface>
</UserInterfaces>
</Package>
custom component script packages/Atlas4500 Tuner/meta/installscript.qs:
var targetDirectoryPage = null;
function Component()
{
installer.gainAdminRights();
component.loaded.connect(this, this.installerLoaded);
}
Component.prototype.createOperations = function()
{
// Add the desktop and start menu shortcuts.
component.createOperations();
component.addOperation("CreateShortcut",
"#TargetDir#/Atlas4500Tuner.exe",
"#DesktopDir#/Atlas4500 Tuner.lnk",
"workingDirectory=#TargetDir#");
component.addOperation("CreateShortcut",
"#TargetDir#/Atlas4500Tuner.exe",
"#StartMenuDir#/Atlas4500 Tuner.lnk",
"workingDirectory=#TargetDir#");
}
Component.prototype.installerLoaded = function()
{
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.addWizardPage(component, "TargetWidget", QInstaller.TargetDirectory);
targetDirectoryPage = gui.pageWidgetByObjectName("DynamicTargetWidget");
targetDirectoryPage.windowTitle = "Choose Installation Directory";
targetDirectoryPage.description.setText("Please select where the Atlas4500 Tuner will be installed:");
targetDirectoryPage.targetDirectory.textChanged.connect(this, this.targetDirectoryChanged);
targetDirectoryPage.targetDirectory.setText(installer.value("TargetDir"));
targetDirectoryPage.targetChooser.released.connect(this, this.targetChooserClicked);
gui.pageById(QInstaller.ComponentSelection).entered.connect(this, this.componentSelectionPageEntered);
}
Component.prototype.targetChooserClicked = function()
{
var dir = QFileDialog.getExistingDirectory("", targetDirectoryPage.targetDirectory.text);
targetDirectoryPage.targetDirectory.setText(dir);
}
Component.prototype.targetDirectoryChanged = function()
{
var dir = targetDirectoryPage.targetDirectory.text;
if (installer.fileExists(dir) && installer.fileExists(dir + "/maintenancetool.exe")) {
targetDirectoryPage.warning.setText("<p style=\"color: red\">Existing installation detected and will be overwritten.</p>");
}
else if (installer.fileExists(dir)) {
targetDirectoryPage.warning.setText("<p style=\"color: red\">Installing in existing directory. It will be wiped on uninstallation.</p>");
}
else {
targetDirectoryPage.warning.setText("");
}
installer.setValue("TargetDir", dir);
}
Component.prototype.componentSelectionPageEntered = function()
{
var dir = installer.value("TargetDir");
if (installer.fileExists(dir) && installer.fileExists(dir + "/maintenancetool.exe")) {
installer.execute(dir + "/maintenancetool.exe", "--script=" + dir + "/scripts/auto_uninstall.qs");
}
}
Custom target directory widget packages/Atlas4500 Tuner/meta/targetwidget.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TargetWidget</class>
<widget class="QWidget" name="TargetWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>190</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>491</width>
<height>190</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="description">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="targetDirectory">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="targetChooser">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="warning">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>122</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
packages/Atlas4500 Tuner/data/scripts/auto_uninstall.qs:
// Controller script to pass to the uninstaller to get it to run automatically.
// It's passed to the maintenance tool during installation if there is already an
// installation present with: <target dir>/maintenancetool.exe --script=<target dir>/scripts/auto_uninstall.qs.
// This is required so that the user doesn't have to see/deal with the uninstaller in the middle of
// an installation.
function Controller()
{
gui.clickButton(buttons.NextButton);
gui.clickButton(buttons.NextButton);
installer.uninstallationFinished.connect(this, this.uninstallationFinished);
}
Controller.prototype.uninstallationFinished = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function()
{
gui.clickButton(buttons.FinishButton);
}
The idea here is to detect if the current directory has an installation in it or not, and, if it does, run the maintenance tool in that directory with a controller script that just clicks through it.
Note that I put the controller script in a scripts directory that is part of the actual component data. You could probably do something cleaner if you have multiple components, but this is what I am using.
You should be able to copy these files for yourself and just tweak the strings to make it work.
I found a way to use rationalcoder's solution without an embedded controller script !
All you have to do is launch the maintenancetool with the purge command and send yes to its standard input.
So replace this line installer.execute(dir + "/maintenancetool.exe", "--script=" + dir + "/scripts/auto_uninstall.qs"); from the component script by this line installer.execute(dir + "/maintenancetool.exe", ["purge"], "yes");
This way, the installation is replaced and the add/remove programs UI in Windows does not contain any duplicates.
For Windows users, make sure that the original installation directory isn't opened by a terminal. If it is, the directory will not get removed and the installation will fail. The directory will remain in a bugged state where you can't remove or access it until you restart your session.
Adding on to rationalcoder and Skeird's answers, when using the purge command with version 4 of the installer framework you cannot just pass in Yes to stdin, you will get an output device is not associated with a terminal error and the maintenance tool will do nothing. You need to use the -c or --confirm argument.
So replace:
installer.execute(dir + "/maintenancetool.exe", "--script=" + dir + "/scripts/auto_uninstall.qs");
or
installer.execute(dir + "/maintenancetool.exe", ["purge"], "yes");
with
installer.execute(dir + "/maintenancetool.exe", ["purge", "-c"]);
I made a hack around. Put it at the end of your installscript.qs.
component.addOperation("AppendFile", "#TargetDir#/cleanup.bat",
"ping 127.0.0.1 -n 4\r\ndel /F /Q maintenancetool.exe \
&& for /F %%L in ('reg query HKEY_USERS /v /f \"#TargetDir#\\maintenancetool.exe\" /d /t REG_SZ /s /e') do \
reg query %%L /v DisplayName \
&& reg delete %%L /f\r\ndel /F /Q cleanup.bat \
&& exit\r\n")
component.addOperation("Execute", "workingdirectory=#TargetDir#",
"cmd", "/C", "start", "/B",
"Cleaning up", "cmd /C ping 127.0.0.1 -n 2 > nul && cleanup.bat > nul")
This will delete the maintenancetool.exe after waiting 3 seconds which causes the installer to merely warn that the target folder is not empty instead of refusing to install. Also it deletes the registry entry for uninstalling the program so it doesn't accumulate in add/remove programs. Obviously after the maintenancetool is deleted you cannot use it anymore for things like uninstalling or updating, but I only support that via running the installer again. The maintenancetool is only written after installation is finished and the cmd start cmd hackery is to make it so the installer doesn't notice that there is a step still running. If you have multiple optional components you may need to increase the delay or make it more robust to check if something is still running.
In theory it should not be necessary to write a batch file and then execute it. You should be able to execute the command directly. In practice I have not found a way to correctly escape quotes to make the right cmd instance evaluate the correct parts.
There are few things you need to do:
To get past of TargetDirectoryPage which you can achieve by adding this code
installer.setValue("RemoveTargetDir", false)
Custom UI (or message box) that allow you to to run this code. This UI should be inserted after the TargetDirectoryPage.
// you need to append .exe on the maintenance for windows installation
installer.execute(installer.findPath(installer.value("MaintenanceToolName"), installer.value("TargetDir")));
Ok, this answer is based on the latest installer framework (3.2.2), I'm not sure if it works for older versions.
To overwrite target dir, you just need set RemoveTargetDir to false in your configuration file:
<RemoveTargetDir>false</RemoveTargetDir>
It worked.
Offical doc explains this element as below:
Set to false if the target directory should not be deleted when uninstalling.
It's a bit confusing if you dont know how it is used:
bool TargetDirectoryPage::validatePage()
{
m_textChangeTimer.stop();
if (!isComplete())
return false;
if (!isVisible())
return true;
///
/// NOTICE HERE:
/// If you set RemoveTargetDir to false, function return true here.
const QString remove = packageManagerCore()->value(QLatin1String("RemoveTargetDir"));
if (!QVariant(remove).toBool())
return true;
const QString targetDir = this->targetDir();
const QDir dir(targetDir);
// the directory exists and is empty...
if (dir.exists() && dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty())
return true;
const QFileInfo fi(targetDir);
if (fi.isDir()) {
QString fileName = packageManagerCore()->settings().maintenanceToolName();
#if defined(Q_OS_MACOS)
if (QInstaller::isInBundle(QCoreApplication::applicationDirPath()))
fileName += QLatin1String(".app/Contents/MacOS/") + fileName;
#elif defined(Q_OS_WIN)
fileName += QLatin1String(".exe");
#endif
QFileInfo fi2(targetDir + QDir::separator() + fileName);
///
/// AND NOTICE HERE:
/// Do exists check here.
if (fi2.exists()) {
return failWithError(QLatin1String("TargetDirectoryInUse"), tr("The directory you selected already "
"exists and contains an installation. Choose a different target for installation."));
}
return askQuestion(QLatin1String("OverwriteTargetDirectory"),
tr("You have selected an existing, non-empty directory for installation.\nNote that it will be "
"completely wiped on uninstallation of this application.\nIt is not advisable to install into "
"this directory as installation might fail.\nDo you want to continue?"));
} else if (fi.isFile() || fi.isSymLink()) {
return failWithError(QLatin1String("WrongTargetDirectory"), tr("You have selected an existing file "
"or symlink, please choose a different target for installation."));
}
return true;
}
Notice comments "NOTICE HERE:".

My Archetypes-based content type can't be added

I'm developing an add-on package which introduces a few Archetypes-based content types;
these are defined in the default profile of that package.
After (re-) installing my package in the Quick-Installer, I can see my types in the types tool; but I can't add them TTW, and they are not listed in the folder_constraintypes_form. I did select them in the "Allowed content types" multiselect list of the Folder portal type.
Since I got a ValueError from FactoryTypeInformation._getFactoryMethod in an bin/instance debug session, I "developed" Products.CMFPlone (branch 2.2) and changed the TypesTool.py like so:
from pprint import pprint # ADDED
...
class FactoryTypeInformation(TypeInformation):
...
def _getFactoryMethod(self, container, check_security=1):
if not self.product or not self.factory:
raise ValueError, ('Product factory for %s was undefined' %
self.getId())
pd = container.manage_addProduct # ADDED
p = container.manage_addProduct[self.product]
self_product = self.product # ADDED
self_factory = self.factory # ADDED
m = getattr(p, self.factory, None)
if m is None:
pprint(locals()) # ADDED
raise ValueError, ('Product factory for %s was invalid' %
self.getId())
if not check_security:
return m
if getSecurityManager().validate(p, p, self.factory, m):
return m
raise AccessControl_Unauthorized( 'Cannot create %s' % self.getId() )
The debug session now looks like this:
>>> root = app.plone
>>> from Products.CMFCore.utils import getToolByName
>>> tmp_folder = root.temp
>>> type_name = 'MyType'
>>> types_tool = getToolByName(tmp_folder, 'portal_types')
>>> type_info = types_tool.getTypeInfo(type_name)
>>> type_info
<DynamicViewTypeInformation at /plone/portal_types/MyType>
>>> new_content_item = type_info._constructInstance(tmp_folder, 'shiny_new_object')
{'check_security': 0,
'container': <ATFolder at /plone/temp>,
'pd': <App.FactoryDispatcher.ProductDispatcher object at 0x227afd0>,
'p': <App.FactoryDispatcher.FactoryDispatcher object at 0x7b97450>,
'self': <DynamicViewTypeInformation at /plone/portal_types/MyType>,
'm': None,
'self_factory': 'addMyType',
'self_product': 'MyCompany.MyProduct'}
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 551, in _constructInstance
m = self._getFactoryMethod(container, check_security=0)
File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 467, in _getFactoryMethod
self.getId())
ValueError: Product factory for MyType was invalid
So, the FactoryDispatcher lacks the necessary addMyType attribute.
Probably my declarations are incomplete?
This is what I have:
config.py:
# -*- coding: utf-8 -*-
from Products.CMFCore.permissions import setDefaultRoles
from os import sep
from .permissions import (AddMyType,
)
PROJECTNAME = "MyCompany.MyProduct"
PRODUCT_HOME = sep.join(__file__.split(sep)[:-1])
MANAGERS_ONLY = ('Manager',)
MANAGERS_AND_OWNER = ('Manager', 'Owner')
# Permissions
DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content"
setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, MANAGERS_AND_OWNER)
ADD_CONTENT_PERMISSIONS = {
'MyType': AddMyType,
}
for perm in ADD_CONTENT_PERMISSIONS.values():
setDefaultRoles(perm, MANAGERS_ONLY)
content/mytype.py:
# -*- coding: utf-8 -*-
__author__ = """unknown <unknown>"""
__docformat__ = 'plaintext'
from AccessControl import ClassSecurityInfo
from zope.interface import implements
from ..interfaces import IMyType
from ..config import PROJECTNAME
from Products.ATContentTypes.content.base import ATCTContent
from Products.ATContentTypes.content.schemata import ATContentTypeSchema
from Products.ATContentTypes.content.base import registerATCT as registerType
MyType_schema = (
ATContentTypeSchema.copy()
)
class MyType(ATCTContent):
"""
description of my type
"""
security = ClassSecurityInfo()
implements(IMyType)
meta_type = 'MyType'
_at_rename_after_creation = True
schema = MyType_schema
registerType(MyType, PROJECTNAME)
interfaces.py:
# -*- coding: utf-8 -*-
"""Module where all interfaces, events and exceptions live."""
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.interface import Interface
class ISupBetonqualiLayer(IDefaultBrowserLayer):
"""Marker interface that defines a browser layer."""
class IMyType(Interface):
"""Marker interface for .mytype.MyType
"""
permissions.py:
# -*- coding: utf-8 -*- vim: ts=8 sts=4 sw=4 si et tw=79
"""
Permissions
"""
AddMyType = 'MyCompany.MyProduct: Add MyType'
profiles/default/factorytool.xml:
<?xml version="1.0"?>
<object name="portal_factory" meta_type="Plone Factory Tool">
<factorytypes>
<type portal_type="MyType"/>
</factorytypes>
</object>
profiles/default/rolemap.xml:
<?xml version="1.0"?>
<rolemap>
<roles>
<role name="MyAuthor"/>
</roles>
<permissions>
<permission name="MyCompany.MyProduct: Add MyType" acquire="True">
<role name="MyAuthor"/>
<role name="Manager"/>
</permission>
</permissions>
</rolemap>
profiles/default/types.xml:
<?xml version="1.0"?>
<object name="portal_types"
meta_type="Plone Types Tool">
<object name="MyType"
meta_type="Factory-based Type Information with dynamic views"/>
</object>
profiles/default/types/MyType.xml:
<?xml version="1.0"?>
<object name="MyType"
meta_type="Factory-based Type Information with dynamic views"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<property name="title">MyType</property>
<property name="description">
Some description text which is indeed visible in the types tool
</property>
<property name="content_icon">SomeExisting.png</property>
<property name="content_meta_type">MyType</property>
<property name="product">MyCompany.MyProduct</property>
<property name="factory">addMyType</property>
<property name="immediate_view">mytype_view</property>
<property name="global_allow">True</property>
<property name="filter_content_types">False</property>
<property name="allowed_content_types">
</property>
<property name="allow_discussion">False</property>
<property name="default_view">mytype_view</property>
<property name="view_methods">
<element value="base_view"/>
</property>
<property name="default_view_fallback">False</property>
<alias from="(Default)" to="(dynamic view)"/>
<alias from="index.html" to="(dynamic view)"/>
<alias from="view" to="(selected layout)"/>
<alias from="edit" to="base_edit"/>
<alias from="properties" to="base_metadata"/>
<action title="View"
action_id="view"
category="object"
condition_expr=""
url_expr="string:${object_url}/view"
visible="True">
<permission value="View"/>
</action>
<action title="Edit"
action_id="edit"
category="object"
condition_expr="not:object/##plone_lock_info/is_locked_for_current_user"
url_expr="string:${object_url}/edit"
visible="True">
<permission value="Modify portal content"/>
</action>
</object>
Should not Archetypes take care of creating that missing addMyType method?
What could make this fail?
Is there something obviously missing in my configuration?
The site contains Archtypes-based objects exclusively so far. Will I come into trouble if I add Dexterity-based types now? ''(I'm totally inexperienced with Dexterity)''
Before someone tells me to do so: I created a question in the Plone community forum already; no luck so far. If important information comes in on either page, I'll sync it.
These are the missing parts to make your contenttype addable:
1.) Register the content-directory in MyCompany/MyProduct/configure.zcml by adding:
<include package=".content" />
2.) Add the file MyCompany/MyProduct/content/configure.zcml with this content:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
i18n_domain="MyCompany.MyProduct">
<class class=".mytype.MyType">
<require
permission="zope2.View"
interface="..interfaces.IMyType"
/>
</class>
</configure>
3.) Fix the then occurring syntax-error in MyCompany/MyProduct/content/mytype.py by replacing class MyType(*basecls) with class MyType(ATCTContent).
And last but not least remove the former attempts of making things work. Best would be to outsource the type to a dedicated pckg and create it with zopeskel, imo.
For the view-error occurring after adding a type, feel free to open a new quest ;-)

Alfresco workflow get triggered multiple times

I am facing problem in triggering workflow.
I have applied rule on a Folder
Definition of rule :
i) When Item are created on enter this folder
ii) Name End With .xml
iii)Execute Script
Script is
function startWorkflow()
{
var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "activiti$Excel_initial_service";
workflow.parameters["bpm:workflowDescription"] = "Excel initial service workflow for : " + document.name;
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 1);
workflow.parameters["bpm:workflowDueDate"] = futureDate;
return workflow.execute(document);
}
function main()
{
startWorkflow();
}
main();
and my workflow definition is
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="Excel_initial_service" name="Excel Initial Service" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
.
.
.
.
<serviceTask id="servicetask1" name="Service Task" activiti:class="*"> </serviceTask>
.
.
.
.
The problem i am facing is service task is getting triggered multiple times for single file entered in the folder and its not getting stopped.
<?xml version="1.0" encoding="UTF-8"?>
<process id="***" name="Excel Generation Service" isExecutable="true">
<startEvent id="starteventexcel1" name="Start"></startEvent>
<intermediateCatchEvent id="timerintermediatecatcheventexcel1" name="TimerCatchEvent1">
<timerEventDefinition>
<timeDuration>PT10S</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
<serviceTask id="servicetaskexcel1" name="Service Task" activiti:class="***"></serviceTask>
<intermediateCatchEvent id="timerintermediatecatcheventexcel2" name="TimerCatchEvent2">
<timerEventDefinition>
<timeDuration>PT10S</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
<endEvent id="endeventexcel1" name="End"></endEvent>
<sequenceFlow id="flowexcel1" sourceRef="starteventexcel1" targetRef="timerintermediatecatcheventexcel1"></sequenceFlow>
<sequenceFlow id="flowexcel2" sourceRef="timerintermediatecatcheventexcel1" targetRef="servicetaskexcel1"></sequenceFlow>
<sequenceFlow id="flowexcel3" sourceRef="servicetaskexcel1" targetRef="timerintermediatecatcheventexcel2"></sequenceFlow>
<sequenceFlow id="flowexcel4" sourceRef="timerintermediatecatcheventexcel2" targetRef="endeventexcel1"></sequenceFlow>
</process>
The first intermediateCatchEvent here will execute your service task every 10 sec. Why using it?
this answer may this will help you.
The class to use is the ClockUtil which changes the internal clock of the engine.
That being said, I checked your test and I saw that you are using the
ProcessEngine eng = ProcessEngineConfiguration
.createStandaloneInMemProcessEngineConfiguration()
.buildProcessEngine();
To get the process engine. That will give you a default engine, with the job executor disabled. The job executor is needed for timer execution. Add following line to building the process engine to make it work:
setJobExecutorActivate(true);
You can refer this question https://community.alfresco.com/thread/219801-problem-with-intermediatecatchevent
you will find some code on github as explained in above referred question https://github.com/Activiti/Activiti/blob/master/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/event/timer/IntermediateTimerEventTest.java

Javascript Bundle Definition in Plone 5

I have define my Resource Directory in configure.zcml:
<plone:static
type="plone"
name="stuff.dropdownmenu"
directory="static" />
I have define my JS Resource in registry.xml:
<records
prefix="plone.resources/stuff"
interface='Products.CMFPlone.interfaces.IResourceRegistry'>
<value key="js">++plone++stuff.dropdownmenu/stuff.js</value>
</records>
My Question: What is the right value of the Element-Tag in the Bundle Definition:
<records
prefix="plone.bundles/stuffdropdown"
interface='Products.CMFPlone.interfaces.IBundleRegistry'>
<value key="resources" purge="false">
<element>???<element>
</value>
<value key="enabled">True</value>
</records>
Is it the stuff part of prefix-Attribute or ++plone++stuff.dropdownmenu/stuff.js ?
best regards
I found in CMFPlone registry.xml that the part of prefix is the right option. The Resource Definition is here in the same file: CMFPlone registry.xml

Spring Webflow - How to Get List of FLOW IDs

What is the best way to get the full list of FLOW IDs generated by Spring Webflow?
Here is my configuration:
<webflow:flow-registry id="flowRegistry"
flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/pageFlows">
<webflow:flow-location-pattern value="/**/*-flow.xml"/>
</webflow:flow-registry>
[UPDATE 1] I should clarify that I want to do this in Java code, not by inspecting my configuration.
[UPDATE 2] answer: requestContext.getActiveFlow().getApplicationContext()
List of flow ids can be identified by the way they are defined in flow-registry. By default, flows will be assigned registry identifiers equal to their filenames minus the file extension, unless a registry base path is defined.
Let me explain this with examples:
Scenario 1:
flow-location and base-path is not specified:
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/pageFlows/example.xml" />
</webflow:flow-registry>
Flow id: example
Scenario 2:
flow-location-pattern and base-path is not specified :
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="/WEB-INF/pageFlows/**/*-flow.xml"/>
</webflow:flow-registry>
If you have flows like /WEB-INF/pageFlows/example1-flow.xml, /WEB-INF/pageFlows/example2-flow.xml, flow ids are: example1-flow, example2-flow respectively.
Scenario 3:
Your own id is specified:
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/pageFlows/example.xml" id="myExampleId" />
</webflow:flow-registry>
Flow id: myExampleId
Scenario 4:
base-path is specified:
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<webflow:flow-location path="/pageFlows/example.xml" />
</webflow:flow-registry>
Flows will now be assigned registry identifiers equal to the the path segment between their base path and file name.
Flow id: pageFlows
Scenario 5:
flow-location-pattern and base-path is specified:
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
Flows will now be assigned registry identifiers equal to the the path segment between their base path and file name.
So if you have flows located in /pageFlows1/example1, /pageFlows2/example2 directories within WEB-INF, flow ids are: pageFlows1, pageFlows2 respectively.
EDIT :
To get flow ids programmatically:
Assuming your flow controller and flowexecutor definitions as below in webflow-config xml file:
<bean name="flowController" class="org.springframework.webflow.executor.mvc.FlowController">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
//flowRegistry is alredy mentioned in your question
<flow:executor id="flowExecutor" registry-ref="flowRegistry">
<flow:repository type="continuation" max-conversations="1" max-continuations="30" />
</flow:executor>
You can retrieve flow definition ids registered as below:
(I am calling this from a Controller which extends AbstractController, thats why you see getServletContext() method)
ApplicationContext context =
(ApplicationContext)getServletContext().getAttribute(
DispatcherServlet.SERVLET_CONTEXT_PREFIX + "yourWebContextName");
FlowController controller = (FlowController)context.getBean("flowController");
FlowExecutorImpl flowExecutorImpl = (FlowExecutorImpl)controller.getFlowExecutor();
FlowDefinitionRegistryImpl flowDefinitionRegistryImpl = (FlowDefinitionRegistryImpl)flowExecutorImpl.getDefinitionLocator();
//Assuming you have log configured
log.info("Registered Flow Ids are:"+flowDefinitionRegistryImpl.getFlowDefinitionIds());
FlowController has access to FlowExecutor(initial point of entry for webflow). FlowExecutor has access to flowDefinitionRegistry where all flows are registered before being served to requests.
Hope this helps.

Resources