MvvmCross passing configuration to configurable plugin loader - plugins

I am creating a portable MockGeoLocationWatcher that one can substitute in place of the concrete implementations of IMvxGeoLocationWatcher until one has an actual device. This should facilitate development and testing of applications that require geo location.
The PluginLoader class for this plugin currently looks like this:
namespace Pidac.MvvmCross.Plugins.Location
{
public class PluginLoader : IMvxConfigurablePluginLoader
{
private bool _loaded;
public static readonly PluginLoader Instance = new PluginLoader();
public void EnsureLoaded()
{
if (_loaded)
return;
_loaded = true;
var locationWatcher = new MockGeoLocationWatcher();
var data = #"<?xml version='1.0' encoding='utf-8'?>
<WindowsPhoneEmulator xmlns='http://schemas.microsoft.com/WindowsPhoneEmulator/2009/08/SensorData'>
<SensorData>
<Header version='1' />
<GpsData latitude='48.619934106826' longitude='-84.5247359841114' />
<GpsData latitude='48.6852544862377' longitude='-83.9864059059864' />
<GpsData latitude='48.8445703681025' longitude='-83.7337203591114' />
<GpsData latitude='48.8662561090809' longitude='-83.2393355934864' />
<GpsData latitude='49.0825970371386' longitude='-83.0415816872364' />
<GpsData latitude='49.2621642999055' longitude='-82.7229781716114' />
<GpsData latitude='49.2621642999055' longitude='-82.6021285622364' />
<GpsData latitude='49.2047736379815' longitude='-82.3054977028614' />
</SensorData>
</WindowsPhoneEmulator>";
locationWatcher.SensorLocationData = data;
Mvx.RegisterSingleton(typeof(IMvxGeoLocationWatcher), locationWatcher);
}
public void Configure(IMvxPluginConfiguration configuration)
{
}
}
public class MockLocationWatcherConfiguration : IMvxPluginConfiguration
{
public static readonly MockLocationWatcherConfiguration Default = new MockLocationWatcherConfiguration();
// ideally, we should use this property to point to a file or string containing location data
// this should be configurable outside of code base.
public string SensorLocationData { get; set; }
}
}
I will like to pass the sensor data, currently hardcoded into the variable called "data" through an instance of MockLocationWatcherConfiguration but do not know where the MvvmCross framework is expecting to load the configuration for this plugin before IMvxConfigurablePluginLoader.Configure(configuration) is invoked. Ideally, I should specify this through configuration.
I looked at the Json plugin's implementation of PluginLoaded but still could not figure out where the configuration was retrieved before a cast was attempted in IMvxConfigurablePluginLoader.Configure.
Any ideas or pointers will be greatly appreciated.
TIA.

This is covered in the draft wiki page https://github.com/slodge/MvvmCross/wiki/MvvmCross-plugins - see "writing a configurable plugin"

Related

Client resources are not loading to custom block

I need help with Client resource importing, According to the documentation I have created ClientResourceProvider and QbankClientResourceRegister. Kindly check the following.
QbankClientResourceRegister :
[ClientResourceRegistrator]
public class QbankClientResourceRegister : IClientResourceRegistrator
{
public void RegisterResources(IRequiredClientResourceList requiredResources)
{
requiredResources.Require("epi-cms.widgets.base").AtHeader();
requiredResources.Require("qbank.picker").AtFooter();
}
}
ClientResourceProvider :
[ClientResourceProvider]
public class ClientResourceProvider : IClientResourceProvider
{
public IEnumerable<ClientResource> GetClientResources()
{
return new[]
{
new ClientResource
{
Name = "epi-cms.widgets.base",
Path = Paths.ToClientResource("QbankModule", "ClientResources/Scripts/Editors/QBankMediaPicker.js"),
ResourceType = ClientResourceType.Script
},
new ClientResource
{
Name = "qbank.picker",
Path = Paths.ToClientResource("QbankModule", "ClientResources/Scripts/qbank-connector.js"),
ResourceType = ClientResourceType.Script
}
};
}
}
module.config file in the moduel folder :
<?xml version="1.0" encoding="utf-8"?>
<module name="QbankModule" loadFromBin="false" clientResourceRelativePath="" viewEngine="Razor" authorizationPolicy="episerver:cmsadmin"
moduleJsonSerializerType="None" preferredUiJsonSerializerType="Net">
<assemblies>
<add assembly="Qbank.Connector.EpiServerModule5" />
<add assembly="Qbank.Connector.EpiCore11" />
<add assembly="Qbank.Connector.EpiCore" />
<add assembly="Qbank.Connector.Core" />
</assemblies>
<clientResources>
<add name="epi-cms.widgets.base" path="ClientResources/Styles/qbankplugin.css" resourceType="Style"/>
<add name="qbank.picker" path="ClientResources/scripts/editors/QbankMediaPicker.js" resourceType="Script"/>
</clientResources>
<dojo>
<paths>
<add name="qbank" path="ClientResources/scripts" />
</paths>
</dojo>
</module>
I need to load QbankMediaPicker.js when loading the following specific block :
[ContentType(
DisplayName = "Banner",
GUID = "0d1c8743-4d48-470f-8afb-7e62d84f6092",
GroupName = SystemTabNames.Content)]
public class BannerBlock : BlockData
{
[Display(
Name = "Header",
Description = "Enter a header for the block",
GroupName = SystemTabNames.Content,
Order = 1
)]
[Required]
public virtual string Header { get; set; }
[Display(
Name = "Description",
Description = "Enter a Description for the block",
GroupName = SystemTabNames.Content,
Order = 2
)]
[Required]
public virtual XhtmlString Description { get; set; }
[Display(
Name = "QBankSampleImage",
Description = "QBankSampleImage for the block",
GroupName = SystemTabNames.Content,
Order = 3)]
//[Qbank.Connector.EpiCore.DataAnnotations.MediaFormat("#310")]
[UIHint(Qbank.Connector.Core.Web.UIHint.QBankMedia)]
public virtual ContentReference QBankSampleImage { get; set; }
Also got this form a forum:
Requiring resources from a partial view/compontent has stopped working in CMS12. The fix will be released in 12.4.0. See forum thread here: https://world.optimizely.com/forum/developer-forum/cms-12/thread-container/2022/2/require-client-resources-only-when-specific-block-type-is-rendered/
Actually, I upgraded EPiServer.Framework and EPiServer.CMS.Core packages to the latest version (12.4.0). But it seems the EPiServer.CMS package does not have version 12.4.* yet. But still, I can't get the client resources imported when I'm creating my custom block.
Regarding the versions, I noticed that fixes will be released on version 12.4.0, so is it on EPiServer.CMS package? or in EPiServer.Framework / EPiServer.CMS.Core packages?
if it is EPiServer.CMS package, does it means that we need to wait for the next release (12.4.0) with the fix? Or do you know any workaround for this?
Your should have something like the following to tell the CMS which client resources your component requires:
public class MyBlockViewComponent : ViewComponent
{
public MyBlockViewComponent(IRequiredClientResourceList requiredClientResourceList)
{
requiredClientResourceList.RequireScript("/scripts/some-script.js, "someName", new[] { "someDependency" }).AtFooter();
}
// ...
}
Also, you need to make sure Footer and/or Header sections are rendered somewhere, for example in your shared layout view, like #Html.RequiredClientResources("Footer").
Edit: Note that you can use slightly different syntax to load a named resource instead of an explicit path, above was just from some sample code.

Is it possible to apply xml Templates in JAVA DSL Runner

we have a lot of old citrus xml Testcases and templates in our Projects. After Upgrading to newer version I decided to make the switch to Java DSL. Is it possible to keep using the old templates? If i Try to do so, I get a "No bean named .. is defined" exception.
I tried the to import the template file via #ImportResource but without success.
You can write a simple custom test action that loads the template and executes it with current test context:
Given the following template in templates/hello-template.xml
<spring:beans xmlns="http://www.citrusframework.org/schema/testcase"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/testcase http://www.citrusframework.org/schema/testcase/citrus-testcase.xsd">
<template name="helloTemplate">
<echo>
<message>Hello ${user}</message>
</echo>
</template>
</spring:beans>
You can write a custom test action for loading that template:
public class TemplateTest extends TestNGCitrusTestRunner {
#Test
#CitrusTest
public void test() {
run(new CallTemplateAction("templates/hello-template.xml", "helloTemplate"));
}
private class CallTemplateAction extends AbstractTestAction {
private final String templateName;
private final String templateLocation;
public CallTemplateAction(String templateLocation, String templateName) {
this.templateLocation = templateLocation;
this.templateName = templateName;
}
#Override
public void doExecute(TestContext testContext) {
Template template = new ClassPathXmlApplicationContext(new String[] { templateLocation },
testContext.getApplicationContext())
.getBean(templateName, Template.class);
template.getParameter().put("user", "foo");
template.execute(testContext);
}
}
}
You should probably cache the template instance and/or close the application context when done with the action.

f:viewAction does not invoke action method

I can't get an action method with the f:viewAction tag to work.
Here's the jsf page:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<ui:repeat var="genreType" value="#{navigation.genreTypeList}">
<f:metadata>
<f:viewParam name="nameEn" value="#{genreType.name_en}" required="true" />
<f:viewAction action="#{search.searchByGenreType}" />
</f:metadata>
<h:link value="#{genreType.name_de}" outcome="index" includeViewParams="true" /><br />
</ui:repeat>
</ui:composition>
It produces links like this:
[...]/index.jsf;jsessionid=635562E66C7F2FA54504B53D5DAA114C?nameEn=fiction
And here's the bean:
#ManagedBean
#RequestScoped
public class Search implements Serializable {
private static final long serialVersionUID = -5193732222381183093L;
private String nameEn;
public String getNameEn() {
return this.nameEn;
}
public void setNameEn(String nameEn) {
this.nameEn = nameEn;
}
// action methods
public String searchByGenreType() {
System.out.println("searchByGenreType");
return "index";
}
}
I'm using JSF 2.2.5 with Tomcat 7.0.42, IDE is Eclipse Kepler (4.3.1).
I've tried different variations (#PostConstruct in bean, explicit navigation in faces-config.xml, old and new namespaces).
There should be no problem with namespaces since this is fixed since JSF 2.2.5.
This code isn't making any sense. You seem to be confusing <f:viewParam> with <f:param>. You need <f:param> to add HTTP request parameters to links. The <f:viewParam> is to be used to set incoming HTTP request parameters as bean properties.
Given the concrete functional requirement of having a list of links with parameters which in turn should on the target page set the parameter as a bean property and invoke a bean action, here's how you should be implementing it:
The source page with the list of links:
<ui:repeat var="genreType" value="#{navigation.genreTypeList}">
<h:link value="#{genreType.name_de}" outcome="index">
<f:param name="nameEn" value="#{genreType.name_en}" />
</h:link>
<br />
</ui:repeat>
In the target page, apparently index.xhtml, put this somewhere in top, right before <h:head>:
<f:metadata>
<f:viewParam name="nameEn" value="#{search.nameEn}" required="true" />
<f:viewAction action="#{search.searchByGenreType}" />
</f:metadata>
Inside the searchByGenreType() method you can just access that nameEn property directly.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When using <ui:composition> templating, where should I declare the <f:metadata>?

how to use zk annotations

I am using zk 5.0.3. I want to use the following annotation binding as the title of a "center" region of a borderlayout:
<a:bind content="entrydisplay.activeEntryCaption" /> <html />
I want to do the following:
<borderlayout>
<north title="use the above binding here">
this is north
</north>
</borderlayout>
How do I achieve the functionality such that I can wrap this binding as the value of the title?
Thanks,
Sony
You are using an outdated version of ZK data binding. It is highly recommended that you make use of the latest methodology.
The following link is the databinding section of the ZK Essential guide & Developer's Reference:
Developer's Reference Databinding
ZK Essential's Databinding
Our basic databinding consists of a POJO which follows the Java bean conventions being access from an XML based interface using annotations in attributes. For example:
Person POJO:
public class Person {
private String _firstName = "";
private String _lastName = "";
private Boolean _married = true;
public Person(){
}
public Person(String firstName, String lastName, Boolean married){
_firstName = firstName;
_lastName = lastName;
_married = married;
}
// getter and setters
public void setFullName(String f) {
// do nothing
}
public String getFullName() {
return _firstName + " " + _lastName;
}
//add more here
}
The UI file:
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<window>
<zscript><![CDATA[
//prepare the person object
import bean.Person;
Person person = new Person();
person.setFirstName("Max");
person.setLastName("Planck");
]]>
</zscript>
<grid width="400px">
<rows>
<row> First Name: <textbox value="#{person.firstName}"/></row>
<row> Last Name: <textbox value="#{person.lastName}"/></row>
<row> Full Name: <label value="#{person.fullName}"/></row>
</rows>
</grid>
</window>
The theory is described here.
i think the old way is done it like this
<borderlayout>
<north>
<attribute name="label">
<a:bind value="entrydisplay.activeEntryCaption" />
</attribute>
</north>
</borderlayout>
The new doc
The doc of [http://docs.zkoss.org/wiki/Data_binding][Data Binding]
For your specific question, annotate your component like following:
<borderlayout>
<north id="mynorth" title="#{entrydisplay.activeEntryCaption}">
this is north
</north>
</borderlayout>
Data binder will read such annotation and call the getter and setter methods to set the title of the north component for you. It will do something like:
mynorth.setTitle(entrydisplay.getActiveEntryCaption());

MEF Contrib Provider Model Not Importing Parts

I have been trying to use the configurable provider model for handling my MEF imports and exports from MEF Contrib (link). I've read the Codeplex documentation and Code Junkie's blog post (link); however, I can't seem to get the container to create the parts. Where am I going wrong?
Program.cs
namespace MEFTest
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
// [ImportMany("command", typeof(IHelp))]
public IEnumerable<IHelp> Commands { get; set; }
void Run()
{
Compose();
foreach(IHelp cmd in Commands)
{
Console.WriteLine(cmd.HelpText);
}
Console.ReadKey();
}
void Compose()
{
var provider = new ConfigurableDefinitionProvider("mef.configuration");
var catalog = new DefinitionProviderPartCatalog<ConfigurableDefinitionProvider>(provider);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
TestCommand.cs
namespace MEFTest
{
//[Export("command", typeof(IHelp))]
public class TestCommand : IHelp
{
private string _helpText = "This is a test.";
public string CommandName
{
get { return "Test"; }
}
public string HelpText
{
get { return _helpText; }
}
}
}
App.Config section:
<mef.configuration>
<parts>
<part type="MEFTest.TestCommand, MEFTest">
<exports>
<export contract="IHelp" />
</exports>
</part>
<part type="MEFTest.Program, MEFTest">
<imports>
<import member="Commands" contract="IHelp" />
</imports>
</part>
</parts>
</mef.configuration>
I don't get any build errors and it runs fine if I switch to the typical attribute-based system that is part of the MEF core (with the appropriate catalog too). Program.Commands is always NULL in the above example. I tried to just use a singular property instead of a collection and get the same results.
When I debug I can get the provider.Parts collection so I know it's accessing the configuration information correctly; however, I get an InvalidOperationException whenever I debug and try to drill into catalog.Parts.
Anyone have any experience as to where I'm going wrong here?
As documented here, you also need this in your config file:
<configSections>
<section
name="mef.configuration"
type="MefContrib.Models.Provider.Definitions.Configurable.PartCatalogConfigurationSection, MefContrib.Models.Provider" />
</configSections>
If you already have that, then it might be interesting to show us the stack trace of the InvalidOperationException that you get when accessing provider.Parts.
I had the same problems and could not get it to work, but here are some details:
It seems that ComposeParts() does not work as expected (at least in the version I used) because it uses static methods, based on Reflection to find all required Imports (so it seems that this part cannot be changed from outside of MEF). Unfortunately we want to use xml configuration and not the MEF attributes.
It works if you add [Import] attributes to the members of the class you you use with ComposeParts(). In your case this would be "Programm". In this case all exports defined in the configuration file will be found.
I could not find any documentation or examples on the MEF Contrib page relating to that problem. Also there is no unittest in the MEF contrib projekt that uses ComposeParts().
A workaround would be to use container.GetExportedValues() to retrieve the values, but in this case you have to set the classes members manually.
Hope that helps.