Image upload component for OpenLaszlo with drag & drop support and preview - file-upload

I haven't seen any good file upload component for OpenLaszlo. Is there an open source version of a file upload component, which supports drag & drop for DHTML and Adobe AIR, and a preview functionality for both runtimes?
Technically it is possible to support the following features:
drag and drop file upload in DHTML for all desktop browsers http://caniuse.com/#feat=dragndrop
preview of images for Webkit browsers and Firefox in DHTML, and for all browsers using a SWF runtime
drag and drop support for Adobe Air applications
Maybe someone has an existing component which could be made open source, and maintained or improved by the community.

There is currently no way to do a File Upload in DHTML (aka HTML5) mode of an OpenLaszlo application since unfortunately there is no way to set the form type to enctype=multipart/form-data in that run-time.
However, you can do a File Upload with the SWF(Flash) mode of an OpenLaszlo application by accessing the low-level Flash API. It is not obvious how to do this so I wrote a class to do this myself a while back, it will work under (Flash) SWF8, SWF9 and SWF10 mode of OpenLaszlo.
I have never tried compiling an OpenLaszlo application to AIR but I believe the Flash Upload will probably work for that case too.
Here is my class, feel free to use it:
( The code is also avaiable here: http://forum.openlaszlo.org/showthread.php?t=14566&highlight=fileReference )
<library>
<switch>
<when property="$as3"><!-- SWF9/SWF10 -->
<!---
CLASS: <fileuploadhelper>
EXTENDS: <node> (lz.node)
DESCRIPTION:
This is the ActionScript3 (AS3) (SWF9/SWF8) version of the Flash file
upload object.
This allows users to upload files when compiled to a Flash Version that
uses ActionScript3 such as Flash 9 or Flash 10.
-->
<class name="fileuploadhelper" extends="node">
<!---
#param string uploadurl: (optional) default upload url to use if none
passed to this.upload()
-->
<attribute name="uploadurl" type="string" />
<!-- #keywords private -->
<!--- #param flash.net.FileReference file_reference: Flash file reference object -->
<attribute name="file_reference" type="expression" value="null" />
<!-- Imports Required for SWF9/SWF10 -->
<passthrough>
import flash.net.FileReference;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLRequest;
</passthrough>
<!-- *** METHODS *** -->
<handler name="oninit">
<![CDATA[
#passthrough {
this.file_reference = new FileReference();
file_reference.addEventListener(Event.SELECT,this.onSelect);
file_reference.addEventListener(Event.COMPLETE, this.onComplete);
file_reference.addEventListener(ProgressEvent.PROGRESS, this.progressHandler);
file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler);
file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.securityErrorHandler);
}#
]]>
</handler>
<!---
Displays file browsing window and allows the user to select a file (or
cancel to close the window).
-->
<method name="browse">
<![CDATA[
#passthrough {
file_reference.browse();
}#
]]>
</method>
<!---
Return name of selected file
#returns string: the filename of the selected file
-->
<method name="getName">
return this.file_reference.name;
</method>
<!--- #keywords private -->
<!---
#param string submit_url: SWF9/10 #passthrough{...} requires URL to be
referenced in an attribute rather than a
locally defined OpenLaszlo variable or
a compilation error occurs.
-->
<attribute name="submit_url" type="string" />
<!---
Uploads the currently selected file.
#param string strURL: (optional) If defined upload the file to this
URL, otherwise upload to this.uploadurl
Note: required if this.uploadurl is not defined.
-->
<method name="upload" args="strURL = false">
<![CDATA[
if (strURL === false)
var strURL = this.uploadurl; // workaround for SWF9/10 compatibility
this.setAttribute('submit_url', strURL);
#passthrough {
var request:URLRequest = new URLRequest(submit_url);
file_reference.upload(request);
}#
]]>
</method>
<!-- * ABSTRACT handlers: Override to do something useful in instance * -->
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when user selects a file.
#param flash.events.Event ev: the select event
-->
<method name="onSelect" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when progress event is captured.
#param {anything} objDummy: SWF8 requires file_reference object here, does nothing in SWF9/10
#param number bytesLoaded: the number of bytes of the file uploaded
#param number bytesTotal: the number of total bytes of the file to be uploaded
-->
<method name="onProgress" args="objDummy, bytesLoaded, bytesTotal">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when a file upload is complete.
#param flash.events.Event ev: the complete event
-->
<method name="onComplete" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when the file upload fails.
#param flash.events.IOErrorEvent/flash.events.securityErrorEvent ev: the Flash Error Event
-->
<method name="onError" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!-- * Internal Private Handlers * -->
<!--- #keywords private -->
<!---
This will pass the progress values to method this.onProgress()
#param flash.events.ProgressEvent ev: the Flash Progress Event
-->
<method name="progressHandler" args="ev=null">
this.onProgress(false, ev.bytesLoaded, ev.bytesTotal);
</method>
<!--- #keywords private -->
<!---
This will catch an ioError and call method this.onError()
#param flash.events.IOErrorEvent ev: the Flash Error Event
-->
<method name="ioErrorHandler" args="ev=null">
if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.ioErrorHandler(): ERROR: ioError detected, could not upload file.');
this.onError(ev);
</method>
<!--- #keywords private -->
<!---
This will catch a securityError and call method this.onError()
#param flash.events.securityErrorEvent ev: the Flash Error Event
-->
<method name="securityErrorHandler" args="ev=null">
if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.securityErrorHandler(): ERROR: securityError detected. Are you sure you are uploading to same domian as this application is being served from?');
this.onError(ev);
</method>
</class>
</when>
<when property="$as2"><!-- SWF8 -->
<!---
CLASS: <fileuploadhelper>
EXTENDS: <node> (lz.node)
DESCRIPTION:
This is the ActionScript2(AS2) (SWF8) version of the Flash file
upload object.
This allows users to upload files when compiled to a Flash Version that
uses ActionScript2 such as Flash 8
-->
<class name="fileuploadhelper" extends="node">
<!---
#param string uploadurl: (optional) default upload url to use if none
passed to this.upload()
-->
<attribute name="uploadurl" />
<!--- #keywords private -->
<!--- #param flash.net.FileReference file_reference: Flash file reference object -->
<attribute name="file_reference" />
<!-- *** METHODS *** -->
<handler name="oninit" args="invoker">
fr = new flash.net.FileReference();
this.setAttribute('file_reference', fr);
fr.addListener(invoker);
</handler>
<!-- *** METHODS *** -->
<!---
Displays file browsing window and allows the user to select a file (or
cancel to close the window).
-->
<method name="browse">
this.file_reference.browse();
</method>
<!---
Return name of selected file
#returns string: the filename of the selected file
-->
<method name="getName">
return this.file_reference.name;
</method>
<!---
Uploads the currently selected file.
#param string strURL: (optional) If defined upload the file to this
URL, otherwise upload to this.uploadurl
Note: required if this.uploadurl is not defined.
-->
<method name="upload" args="strURL">
if (strURL == null)
var strURL = this.uploadurl;
this.file_reference.upload(strURL);
</method>
<!-- * ABSTRACT HANDLERS * -->
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when user selects a file.
#param flash.events.Event ev: the select event
-->
<method name="onSelect" args="ev=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when progress event is captured.
#param flash.net.fileReference fr: file_reference object here
#param number bytesLoaded: the number of bytes of the file uploaded
#param number bytesTotal: the number of total bytes of the file to be uploaded
-->
<method name="onProgress" args="fr, bytesLoaded, bytesTotal">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when a file upload is complete.
#param flash.events.Event fr: the file_reference object
-->
<method name="onComplete" args="fr=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
<!--- #keywords abstract -->
<!---
ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL
Called when the file upload fails.
#param flash.events.Event fr: the file_reference object
-->
<method name="onError" args="fr=null">
if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
</method>
</class>
</when>
</switch>
</library>
Note: This works similar to an HTML form where you post the file upload to a receiving script on the backend (could be in PHP, ASP, etc.) which would process the file and store it somewhere, there are many tutorials on the web on how to do that so I have not included it. As for drag and drop and preview you would have to write a fairly complicated application in OpenLaszlo yourself to do this, I suggest you view the tutorials and OpenLaszlo documentation to learn how to do that.

Related

Register a Bluetooth agent with Python DBus to hci1 (not hci0)

I have been using copy, paste, and magic to register a Bluetooth agent via Python DBUs which works great for hci0, but I cannot for the life of me see how I can get this agent to work for other Bluetooth controllers, i.e hci1. I have tried selecting the controller and setting it as default in bluetoothctl and other side channels.
Can someone please show me where the agent is associated with the controller. This is all too magical.
I am also unable to find the agent or anything on it with D-Feet - How should or could I find it please?
A dumb toy example is as:
import dbus
import dbus.service
AGENT_PATH = "/org/bluez/anAgent"
class Agent(dbus.service.Object):
#dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def AuthorizeService(self, device, uuid):
print("Some stuff and things")
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
capability = "DisplayYesNo"
agent = Agent(bus, AGENT_PATH)
obj = bus.get_object("org.bluez", "/org/bluez")
# Create the agent manager
manager = dbus.Interface(obj, "org.bluez.AgentManager1")
manager.RegisterAgent(AGENT_PATH, capability)
manager.RequestDefaultAgent(AGENT_PATH)
When Bluetooth needs an agent it looks at the org.bluez.AgentManager1 interface at the /org/bluez D-Bus object path for the location of the agent that has been registered. It then calls the relevant method on the org.bluez.Agent1 interface at that registered object path (/org/bluez/anAgent in your example). The methods that need to be implemented for the org.bluez.Agent1 interface are documented at:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt
There is only one agent irrespective of how many adapters there are on your system.
Could the issue be that the device being paired is associated with the "wrong" adapter?
The Device API has an Adapter property which tracks the object path of the adapter the device belongs to.
To find the agent that you have created it can be useful to use busctl. Using busctl list will list all the available SystemBus services. As you are not claiming a bus name for the agent it will be anonymous so in the format of :x.xxx. This can be a long list so busctl list | grep python is what I usually do to narrow the list down.
To introspect what was there you would do something like:
$ busctl introspect :1.174 /org/bluez/anAgent
To test the agent service that has been published:
$ busctl call :1.174 /org/bluez/anAgent org.bluez.Agent1 AuthorizeService os /org/bluez/hci1/dev_12_34_56_78 1234
This service will need to be asynchronous so you will need to start the MainLoop event loop.
Below is a full example of creating an Agent using pydbus D-Bus bindings.
The only place that the adapter is mentioned is the instruction to start discovery.
If you had another device trying to discover your device with the agent, then it will depend on which adapter is discoverable and/or the other device tries to connect to.
import threading
import pydbus
from gi.repository import GLib
BUS_NAME = 'org.bluez'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
ADAPTER_IFACE = 'org.bluez.Adapter1'
AGENT_PATH = '/org/bluez/anAgent'
AGNT_MNGR_PATH = '/org/bluez'
DEVICE_IFACE = 'org.bluez.Device1'
CAPABILITY = 'KeyboardDisplay'
bus = pydbus.SystemBus()
class Agent:
"""
<node>
<interface name="org.bluez.Agent1">
<method name="Release" />
<method name="RequestPinCode">
<arg name="device" direction="in" type="o" />
<arg name="pincode" direction="out" type="s" />
</method>
<method name="DisplayPinCode">
<arg name="device" direction="in" type="o" />
<arg name="pincode" direction="in" type="s" />
</method>
<method name="RequestPasskey">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="out" type="u" />
</method>
<method name="DisplayPasskey">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="in" type="u" />
<arg name="entered" direction="in" type="q" />
</method>
<method name="RequestConfirmation">
<arg name="device" direction="in" type="o" />
<arg name="passkey" direction="in" type="u" />
</method>
<method name="RequestAuthorization">
<arg name="device" direction="in" type="o" />
</method>
<method name="AuthorizeService">
<arg name="device" direction="in" type="o" />
<arg name="uuid" direction="in" type="s" />
</method>
<method name="Cancel" />
</interface>
</node>
"""
def Release(self):
print('Release')
def RequestPinCode(self, device):
print('RequestPinCode', device)
return '1234'
def DisplayPinCode(self, device, pincode):
print('DisplayPinCode', device, pincode)
def RequestPasskey(self, device):
print('RequestPasskey', device)
return 1234
def DisplayPasskey(self, device, passkey, entered):
print('DisplayPasskey', device, passkey, entered)
def RequestConfirmation(self, device, passkey):
print('RequestConfirmation', device, passkey)
def RequestAuthorization(self, device):
print('RequestAuthorization', device)
def AuthorizeService(self, device, uuid):
print('AuthorizeService', device, uuid)
def Cancel(self):
return
def pair_reply(*args):
print('reply', args)
def pair_error(*args):
print('error', args)
def dbus_path_up(dbus_obj):
return '/'.join(dbus_obj.split('/')[:-1])
def device_found(dbus_obj, properties):
adapter = bus.get(BUS_NAME, dbus_path_up(dbus_obj))
device = bus.get(BUS_NAME, dbus_obj)
print('Stopping discovery')
adapter.StopDiscovery()
if device.Paired:
device.Connect()
else:
print('Pairing procedure starting...')
device.Pair()
def interface_added(path, ifaces):
if DEVICE_IFACE in ifaces.keys():
dev_name = ifaces[DEVICE_IFACE].get('Name')
print('Device found:', dev_name)
if dev_name == 'HC-06':
device_found(path, ifaces[DEVICE_IFACE])
def publish_agent():
bus.register_object(AGENT_PATH, Agent(), None)
aloop = GLib.MainLoop()
aloop.run()
print('Agent Registered')
def create_agent():
thread = threading.Thread(target=publish_agent, daemon=True)
thread.start()
print('Agent running...')
def my_app(hci_idx=0):
adapter_path = f'/org/bluez/hci{hci_idx}'
mngr = bus.get(BUS_NAME, '/')
mngr.onInterfacesAdded = interface_added
create_agent()
agnt_mngr = bus.get(BUS_NAME, AGNT_MNGR_PATH)[AGNT_MNGR_IFACE]
agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
print('Agent registered...')
adapter = bus.get(BUS_NAME, adapter_path)
# adapter.StartDiscovery()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
adapter.StopDiscovery()
if __name__ == '__main__':
my_app()

Read properties from database and use it instead of mule-app.properties

I have been able to read the properties from a table in the database as it was described here Reading mule config from database
Now, I am not able to apply these properties to the flow configs and also access them as out bound properties in the Java Processor classes through the MuleEventContext's message.
Update: below is my flow XML code
<flow name="push-data">
<poll doc:name="Push Poll">
<fixed-frequency-scheduler frequency="${push.data.poll.frequency}" timeUnit="MINUTES" />
<set-property propertyName="tempFilePath" value="${temp.csv.file.path}" doc:name="Property"/>
<component class="com.reports.processors.PushDataProcessor" doc:name="PushDataProcessor"/>
<logger message="worked!!!" level="INFO" doc:name="Logger"/>
<exception-strategy ref="push-report-data_Catch_Exception_Strategy" doc:name="Reference Exception Strategy"/>
</flow>
I am trying to set the properties "push.data.poll.frequency" and "temp.csv.file.path". Earlier, these properties existed in the "mule-app.properties" file.
So, My question is, How do I set the properties loaded from the database to the flow. Please keep in mind that I have already loaded the properties from the database as described in the link above. I just want to be able to set these properties to the flow rather than taking them from the mule-app.properties.
EDIT: To add some more information,
I am using a class with #Configuration annotation. The class as described in the link above, loads the properties from the database. Below is the source code.
#Configuration(name="databasePropertiesProvider")
#Component
public class DatabasePropertiesProvider {
#Autowired(required=true)
private MyService myService;
#Bean
public Properties getProperties() throws Exception {
Properties properties = new Properties();
// get properties from the database
Map<String,String> propertiesMap = myService.getMuleAppPropertiesFromDB();
if(null != propertiesMap && !CollectionUtils.isEmpty(propertiesMap))
properties.putAll(propertiesMap);
return properties;
}
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}}
But this class runs after the app is initialized. Previously, I had configured the PropertySourcesPlaceholderConfigurer in the xml config with the factory-bean as the DatabasePropertiesProvider class. But since DatabasePropertiesProvider has a dependency on MyService class, and the dependency was not getting resolved due to MyService bean not initializing in the container before the property config, I had to make some changes to DatabasePropertiesProvider(the version above) so that this runs after the app initialization.
But now, the problem is that I am unable to access those properties that are loaded from the database.
UPDATE 2: I found a solution. Apparently I was trying to autowire the #Service MyService in the databasePropertiesProvider class. The autowiring was failing with null due to which I made some more modifications to the databasePropertiesProvider class so that It runs after the app is initialized.
Now when I look at it, I realized that I dont need to connect to the database through all the service and repository layers. I moved the query execution code from the repository class to the databasePropertiesProvider class and now the properties are loaded during initialization time and the flows can get the properties without making any changes.
Thanks for all your help guys. Made me do a lot of thinking.
Regards,
Zulfiqar
I found a solution. Apparently I was trying to autowire the #Service MyService in the databasePropertiesProvider class. The autowiring was failing with null due to which I made some more modifications to the databasePropertiesProvider class so that It runs after the app is initialized.
Now when I look at it, I realized that I dont need to connect to the database through all the service and repository layers. I moved the query execution code from the repository class to the databasePropertiesProvider class and now the properties are loaded during initialization time and the flows can get the properties without making any changes.
The whole code looks like this
XML Config:-
<bean class="net.intigral.reports.provider.properties.DatabasePropertiesProvider" id="databasePropertiesProvider">
<property name="entityManager" ref="entityManager" />
</bean>
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="properties">
<bean factory-bean="databasePropertiesProvider" factory-method="getProperties" />
</property>
</bean>
Java Code:-
public class DatabasePropertiesProvider {
EntityManager entityManager;
public Properties getProperties() throws Exception {
Properties properties = new Properties();
// get properties from the database
Map<String,String> propertiesMap = getMuleAppPropertiesFromDB();
if(null != propertiesMap && !CollectionUtilsIntg.isEmpty(propertiesMap))
properties.putAll(propertiesMap);
return properties;
}
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#SuppressWarnings("unchecked")
private Map<String,String> getMuleAppPropertiesFromDB() {
Map<String,String> collect = null;
String query = "select key, value from MuleAppProps muleAppProps";
List<Object[]> results = entityManager.createQuery(query).getResultList();
if (CollectionUtilsIntg.isNotEmpty(results)) {
collect = results.stream().collect(Collectors.toMap(o -> (String)o[0], o -> (String)o[1]));
}
return collect;
}}
Now, I am able to load the properties the same way I used to load from mule-app.properties in the FLOWs.
Let your db contains following properties values with key/value pair as below :-
A simple example like below you can refer to read values from Database:-
<spring:beans>
<spring:bean id="dataSource" name="myCon" class="org.enhydra.jdbc.standard.StandardDataSource">
<spring:property name="url" value="jdbc:sqlserver://YourIpAddress\\SQLEXPRESS:1433;databaseName=YourDB;user=sa;password=yourDBPassword" />
<spring:property name="driverName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
</spring:bean>
<!-- Required to connect to datasource -->
<spring:bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<spring:property name="properties" ref="CommonsConfigurationFactoryBean" />
</spring:bean>
<spring:bean name="CommonsConfigurationFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<spring:constructor-arg ref="DatabaseConfiguration" />
</spring:bean>
<spring:bean name="DatabaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">
<spring:constructor-arg type="javax.sql.DataSource" ref="dataSource" />
<spring:constructor-arg index="1" value="YourTableName" />
<spring:constructor-arg index="2" value="Key" />
<spring:constructor-arg index="3" value="Value" />
</spring:bean>
</spring:beans>
<db:generic-config name="Database_Configuration" dataSource-ref="dataSource" doc:name="Generic Database Configuration" />
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration" />
<flow name="firstflow" processingStrategy="synchronous">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP" />
<set-payload value="File name ${file.name} File path ${file.path}" doc:name="Set Payload" />
</flow>
You need to add commons-configuration.jar, spring.jar and spring-modules-jakarta-commons.jar in your classpath
If you want to access properties values in Java class you can inject it using Spring property in init-method of Spring bean.
refer:- http://www.codeproject.com/Articles/28893/Loading-Application-Properties-from-a-Database

jasypt property placeholder not working

I have this properties file:
secret.key = ENC(foobar)
region = ABC
Then in the config.xml:
<spring:beans>
<encryption:encryptor-config id="eConf" password-sys-property-name="MULE_ENCRYPTION_PASSWORD" algorithm="PBEWithMD5AndDES" password="" />
<encryption:string-encryptor id="stringEnc" config-bean="eConf" />
<encryption:encryptable-property-placeholder encryptor="stringEnc" location="${env}.properties" />
</spring:beans>
But the property placeholders don't work, for example:
<sqs:config secretKey="${secret.key}" region="${region}"></sqs-config>
Does anyone know why?
Encrypted password needs to be write within ENC() function and should be encrypted.
Let's consider in properties file where password value is Login#123... Now the encrypted value in properties file will be :-
password=ENC(B0u7D8wLwq/ugin31KNpP78gBcLP7VIN)
Step1 :- We can generate Key using following commands in Command prompt of \jasypt-1.9.2\bin directory :- encrypt input="Login#123" password=sqlpassword algorithm=PBEWithMD5AndDES
Step2 :- In runtime Environment we need to give (Right click->Run As->Run Configuration->Environment) :- Variable :- MULE_ENCRYPTION_PASSWORD and Value:-sqlpassword
In your Mule config, you need configure it as following :-
<spring:beans>
<spring:bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<spring:property name="algorithm" value="PBEWithMD5AndDES"/>
<spring:property name="passwordEnvName" value="MULE_ENCRYPTION_PASSWORD"/>
</spring:bean>
<!-- The will be the encryptor used for decrypting configuration values. -->
<spring:bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<spring:property name="config" ref="environmentVariablesConfiguration"/>
</spring:bean>
<!-- The EncryptablePropertyPlaceholderConfigurer will read the -->
<!-- .properties files and make their values accessible as ${var} -->
<!-- Our "configurationEncryptor" bean (which implements -->
<!-- org.jasypt.encryption.StringEncryptor) is set as a constructor arg. -->
<spring:bean id="propertyConfigurer" class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
<spring:constructor-arg ref="configurationEncryptor"/>
<spring:property name="locations">
<spring:list>
<spring:value>conf/yourPropertyFile.properties</spring:value>
</spring:list>
</spring:property>
</spring:bean>
Then you can use encrypted values like :- ${password}
Reference :- http://blogs.mulesoft.org/encrypting-passwords-in-mule/
and http://pragmaticintegrator.wordpress.com/2014/03/09/using-encrypted-passwords-with-mule-esb/
and https://code.google.com/p/soi-toolkit/issues/detail?id=183
and http://soi-toolkit.googlecode.com/svn-history/r2022/wiki/UG_PropertyFile.wiki
I had similar issue, i did configure everything as explained in Activemq web site . In my case issue was PropertyPlaceholderConfigurer bean was loaded for to load other properties before the EncryptablePropertyPlaceholderConfigurer bean. So remove PropertyPlaceholderConfigurer bean's if any just add EncryptablePropertyPlaceholderConfigurer bean even for other non-encrypted properties as explained in Activemq then it works fine.

Spring Webflow - IllegalStateException when using multipart/form-data and file upload

I am trying to add file upload to my Spring Webflog form processing. As far as the form enctype is not set to multipart/form-data, form submition works just fine. But after I added enctype="multipart/form-data" to my Spring form, this Exception occurs:
java.lang.IllegalStateException: A flow execution action URL can only be obtained in a RenderRequest or a ResourceRequest
at org.springframework.webflow.context.portlet.PortletExternalContext.getFlowExecutionUrl(PortletExternalContext.java:215)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.getFlowExecutionUrl(RequestControlContextImpl.java:178)
at org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:189)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:293)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:242)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:220)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.portlet.FlowHandlerAdapter.handleAction(FlowHandlerAdapter.java:161)
at org.springframework.web.portlet.DispatcherPortlet.doActionService(DispatcherPortlet.java:670)
at org.springframework.web.portlet.FrameworkPortlet.processRequest(FrameworkPortlet.java:520)
at org.springframework.web.portlet.FrameworkPortlet.processAction(FrameworkPortlet.java:461)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:71)
I have added CommonsMultipartResolver to my spring context:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- Limit uploads to one byte smaller than the server is allowed to handle -->
<property name="maxUploadSize" value="100000" />
</bean>
and have commons-fileupload.jar in my pom.xml:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
My JSP looks like this:
<portlet:actionURL var="processFormAction" >
<portlet:param name="execution" value="${flowExecutionKey}"/>
</portlet:actionURL>
<form:form action="${processFormAction}" modelAttribute="customerModel" enctype="multipart/form-data" method="post" >
<form:input path="firstName" cssClass="input-size-1 valid-required" />
<form:input path="lastName" cssClass="input-size-1 valid-required" />
<input name="avatar" id="avatar" type="file"/>
<input type="submit" name="_eventId_submit" id="send" value="Submit"/>
</form:form>
My flow.xml definition:
<view-state id="state1" model="customerModel">
...
<transition on="submit" to="submitFormActions"/>
</view-state>
<action-state id="submitFormActions">
<evaluate expression="portletAction.processForm(customerModel, flowRequestContext)" />
<transition on="success" to="state2"/>
<transition on="error" to="state1" />
</action-state>
The model object:
public class CustomerModel implements Serializable{
private String firstName;
private String lastName;
private MutlipartFile avatar;
...
//public getters and setters
}
Any thoughts what could be wrong? As I said, without enctype="multipart/form-data" the form processing works well.
Thanks
You are using org.springframework.web.multipart.commons.CommonsMultipartResolver which is not aware about the portlet context.
You need to change CommonsMultipartResolver to:
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Also, for this bean to be recognised by DispatcherPortlet, you need to define this bean id as mentioned above. The doc says:
Any configured PortletMultipartResolver bean must have the following id (or name): "portletMultipartResolver".
If you have defined your PortletMultipartResolver with any other name, then the DispatcherPortlet will not
find your PortletMultipartResolver, and consequently no multipart support will be in effect.

Forward call to Action class when validation fails

I'm working on struts 1.1 application.
I have added validation for JSP form page(i.e. adduser.jsp).
It get validated after clicking on add button. And my validation in "Validator-XSS.xml" working fine.
But when validation fails then it forward to input attribute which is jsp form page(i.e. adduser.jsp).
Here I need to forward callto another action
(i. e.openAddUser.do)
which open JSP form page(i.e. adduser.jsp) insted of JSP page.
UPDATE
struts-config.xml
<struts-config>
<!-- some another entries -->
<form-bean name="UserForm" type="com.UserForm"/>
<action path="/createuser" type="com.CreateUserAction" name="UserForm"
scope="request">
<forward name="adduser" path="/jsp/adduser.jsp"/>
</action>
<action path="/adduser" type="com.AddUserAction" input="/jsp/adduser.jsp"
name="UserForm" scope="request">
<forward name="showuser" path="/showUserDetails.do"/>
</action>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/User-Validator.xml"/>
</plug-in>
</struts-config>
XSS-validator.xml
<form-validation>
<formset>
<form name="UserForm">
<field property="userName" depends="mask">
<msg name="mask" key="ui.field.invalidvalue" bundle="appResources"/>
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-Z0-9-_]*$</var-value>
</var>
</field>
</form>
</formset>
on clicking on create user in jsp file it will call createuser.do It will open adduser.jsp
after entering details in form and click on add button it will adduser.do
also it get vlidated through XSS-validator.xml
but call goes to jsp/adduser.jsp but i need it has to call createuser.do
ActionForm is extended by ValidatorForm
public class UserForm extends ValidatorForm{
String userName;
String userId;
//getter setter
}
ActionClass
Public Class CreateUserAction{
public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//some code to bring list and other details
mapping.findForward("adduser");
}
Public Class AddUserAction{
public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//some code to add user and other details
mapping.findForward("showuser");
}
That is because you are not calling that action with the path. try this use this way to call that method that will work and will solve you problem.
Call Method and action
That will work accordingly. to call that action.