I have an eclipse plugin and I want to perform certain action inside this plugin but after eclipse application is opened.
I tried to do it through overriding
public void postWindowCreate()
but it seems that I can't get inside this function when launching the application
Any ideas ?
Do you use e4? Then maybe the following link may help: http://www.eclipse.org/forums/index.php/m/886197/
Edit:
OK, do you define your own application?
Are the methods provided by org.eclipse.ui.application.WorkbenchWindowAdvisor the ones you need? (e.g. preWindowOpen(), preWindowShellClose(), postWindowRestore(), postWindowCreate(), ...)
I also needed that functionality, so here's how I do it:
You need 3 classes, one implementing org.eclipse.equinox.app.IApplication e.g. MyApp, one which extends org.eclipse.ui.application.WorkbenchAdvisor e.g. MyAdvisor, and one which extends org.eclipse.ui.application.WorkbenchWindowAdvisor e.g. MyWindowAdvisor.
Then in MyApp you will probably call something like
PlatformUI.createAndRunWorkbench(display, new MyAdvisor());
where you actually start the workbench and provide your own WorkbenchWindowAdvisor. In MyAdvisor you have to overwrite:
#Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
return new MyWindowAdvisor(configurer);
}
in which you provide your WorkbenchWindowAdvisor. In class MyWindowAdvisor you can finally override the appropriate functions, e.g.
#Override
public void postWindowOpen() {
//TODO
}
Of course you have to run the appropriate application for this to work ;)
OK, now, to provide arbitrary plug-ins to deal with these events, you could define an extension point.
First you need an interface which defines the "events" you want to listen to, e.g.:
public interface IWorkbenchWindowAdvisorHook
{
/**
* Performs arbitrary actions before the window is opened.
* <p>
* This method is called before the window's controls have been created.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* Typical clients will use the window configurer to tweak the
* workbench window in an application-specific way; however, filling the
* window's menu bar, tool bar, and status line must be done in
* {#link ActionBarAdvisor#fillActionBars}, which is called immediately
* after this method is called.
* </p>
*/
void preWindowOpen();
/**
* Performs arbitrary actions as the window's shell is being closed
* directly, and possibly veto the close.
* <p>
* This method is called from a ShellListener associated with the window,
* for example when the user clicks the window's close button. It is not
* called when the window is being closed for other reasons, such as if the
* user exits the workbench via the {#link ActionFactory#QUIT} action.
* Clients must not call this method directly (although super calls are
* okay). If this method returns <code>false</code>, then the user's
* request to close the shell is ignored. This gives the workbench advisor
* an opportunity to query the user and/or veto the closing of a window
* under some circumstances.
* </p>
*
* #return <code>true</code> to allow the window to close, and
* <code>false</code> to prevent the window from closing
* #see org.eclipse.ui.IWorkbenchWindow#close
* #see WorkbenchAdvisor#preShutdown()
*/
public boolean preWindowShellClose();
/**
* Performs arbitrary actions after the window has been restored,
* but before it is opened.
* <p>
* This method is called after a previously-saved window has been
* recreated. This method is not called when a new window is created from
* scratch. This method is never called when a workbench is started for the
* very first time, or when workbench state is not saved or restored.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* It is okay to call <code>IWorkbench.close()</code> from this method.
* </p>
*
* #exception WorkbenchException thrown if there are any errors to report
* from post-restoration of the window
*/
void postWindowRestore() throws WorkbenchException;
/**
* Performs arbitrary actions after the window has been created (possibly
* after being restored), but has not yet been opened.
* <p>
* This method is called after the window has been created from scratch,
* or when it has been restored from a previously-saved window. In the latter case,
* this method is called after <code>postWindowRestore</code>.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowCreate();
/**
* Performs arbitrary actions after the window has been opened (possibly
* after being restored).
* <p>
* This method is called after the window has been opened. This method is
* called after the window has been created from scratch, or when
* it has been restored from a previously-saved window.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowOpen();
/**
* Performs arbitrary actions after the window is closed.
* <p>
* This method is called after the window's controls have been disposed.
* Clients must not call this method directly (although super calls are
* okay). The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowClose();
}
Then the extension point schema (replace all "YOUR-xxx" with your own package/plug-in names, and namespace):
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="***YOUR-NAMESPACE***" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="***YOUR-PLUGIN***" id="workbenchWindowHook" name="***YOUR-PACKAGE***.workbenchWindowHook"/>
</appInfo>
<documentation>
An extension to actively hook into the WorkbenchWindowAdvisor's pre/post methods from other plug-ins.
This is primarily intended for plug-ins that are optional or restricted to some specific products.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="class" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="class">
<annotation>
<documentation>
The hook class implementing IWorkbenchWindowAdvisorHook.
</documentation>
</annotation>
<complexType>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
The hook class implementing IWorkbenchWindowAdvisorHook.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":***YOUR-PACKAGE***.IWorkbenchWindowAdvisorHook"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
</documentation>
</annotation>
</schema>
Then, in your MyWindowAdvisor you need to keep a reference to the extensions
// the reference list
private List<IWorkbenchWindowAdvisorHook> hooks = new ArrayList<IWorkbenchWindowAdvisorHook>();
load/initialize the extensions
//code for initializing the extensions, must be called in the constructor
private void initExtensions()
{
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(
IWorkbenchWindowAdvisorHook.ID);
for(IConfigurationElement element : config)
{
try
{
final Object o = element.createExecutableExtension("name"); //$NON-NLS-1$
if(o instanceof IWorkbenchWindowAdvisorHook)
{
hooks.add((IWorkbenchWindowAdvisorHook)o);
}
}
catch(CoreException e)
{
e.printStackTrace();
}
}
}
and in each "event" function call the extensions' methods:
// example method preWindowOpen()
public void preWindowOpen()
{
for(IWorkbenchWindowAdvisorHook hook : hooks)
{
try
{
hook.preWindowOpen();
}
catch(Throwable t)
{
CorePlugin.logDefaultError(t);
}
}
}
The final step is to provide an extension and class in each plug-in you need to listen to these workbench window events.
Related
So currently i'm working on a TYPO3 extension using a Relation (1:n) to a specific class that provides objects to the main class. Let me explain a bit more in detail: I have a class, that next to normal properties, has a relation to a class that provides objects for some kind of checklist. The idea is that the FE user should be able to add new checklist entries, that's why i use that kind of concept. Initially it would look like this for the edit Action (the [x] represent that it's just a checklist):
main class
property of main class of type boolean [x]
attached object with a string and a boolean property [x]
attached object with a string and a boolean property [x]
property of main class of type text (for comments)
The FE user should be able to edit the record, so he should set the checklist entires to true or false, but even though the checklist entries appear, even those of the attached objects, they aren't persisted, only the properties of the main class are persisted when the FE user edits the records in the FE.
Here is my code:
The domain model of the main class (just the lines that specify the relation to the class that "provides" the objects). Keep in mind that few objects of the related class are attached to the main class when a record of the main class is created, the specific code just isn't in the main classe's controller...
/**
* zugewCheckobject
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Kundentermine\Domain\Model\Checkobject>
* #cascade remove
*/
protected $zugewCheckobject = null;
public function __construct()
{
$this->zugewCheckobject = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Initializes all ObjectStorage properties
* Do not modify this method!
* It will be rewritten on each save in the extension builder
* You may modify the constructor of this class instead
*
* #return void
*/
protected function initStorageObjects()
{
$this->zugewCheckobject = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Adds a Checkobject
*
* #param \...\Kundentermine\Domain\Model\Checkobject $zugewCheckobject
* #return void
*/
public function addZugewCheckobject(\...\Kundentermine\Domain\Model\Checkobject $zugewCheckobject)
{
$this->zugewCheckobject->attach($zugewCheckobject);
}
/**
* Removes a Checkobject
*
* #param \...\Kundentermine\Domain\Model\Checkobject $zugewCheckobjectToRemove The Checkobject to be removed
* #return void
*/
public function removeZugewCheckobject(\...\Kundentermine\Domain\Model\Checkobject $zugewCheckobjectToRemove)
{
$this->zugewCheckobject->detach($zugewCheckobjectToRemove);
}
/**
* Returns the zugewCheckobject
*
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Kundentermine\Domain\Model\Checkobject> $zugewCheckobject
*/
public function getZugewCheckobject()
{
return $this->zugewCheckobject;
}
/**
* Sets the zugewCheckobject
*
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Unilab\Kundentermine\Domain\Model\Checkobject> $zugewCheckobject
* #return void
*/
public function setZugewCheckobject(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $zugewCheckobject)
{
$this->zugewCheckobject = $zugewCheckobject;
}
The edit and update Actions in the controller of the main class...
public function editAction(\...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch)
{
$this->view->assign('kaufmnnisch', $kaufmnnisch);
}
/**
* action update
*
* #param \...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch
* #return void
*/
public function updateAction(\...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch)
{
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$checkobjectRepository = $objectManager->get(\...\Kundentermine\Domain\Repository\CheckobjectRepository::class);
foreach($kaufmnnisch->getZugewCheckobject() as $chk){
$checkobjectRepository->update($chk);
}
$this->kaufmnnischRepository->update($kaufmnnisch);
$this->redirect('list');
}
Part of the "edit" template. I pass the object "kaufmnnisch" as arguments to a partial of the class Chekobject (as it has objects of that class attached to it) and of course to a partial of the class Kaufmnnisch...
<f:section name="main">
<h1>Edit Kaufmnnisch</h1>
<f:flashMessages />
<f:render partial="FormErrors" arguments="{object:Kaufmnnisch}" />
<f:form action="update" name="kaufmnnisch" object="{kaufmnnisch}" >
<f:render partial="Checkobject/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:render partial="Kaufmnnisch/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:form.submit value="Save" />
</f:form>
</f:section>
Again: The problem is that only the properties of the main class get edited not those of the related objects. My assumption is that the Edit template or the partials aren't correctly set.
Edit: Here is the code for the partial of the Checkobject class that gets the object Kaufmnnisch as an argument passed.
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:for each="{kaufmnnisch.zugewcheckobject}" as="chk" >
<f:form.checkbox property="checked" value="0" /><br />
</f:for>
</html>
So basically "zugewcheckobject" is my object storage. Each checkbox gets rendered in the Edit template (thanks to the for each viewhelper), but the values for the boolean properties of each Checkobject object aren't persisted if the user clicks on the "save" button.
Edit2: A var_dump within the updateAction (within the foreach loop) reveals that the "Checked" property of each Checkobject object isn't changed, so it's not only not persisted, but the changed values aren't passed from the Edit template to the updateAction.
Edit3: Acessing every Checkobject object (here: $chk) via the objectstorage "zugewcheckobject" of the passed object of the class "Kaufmnnisch" in the Edit template is possible though, i just cant change the specific properties of the Checkobject objects, because JUST the Kaufmnnisch object is passed back to the updateAction of the specific controller, not each Checkobject of the objectstorage ("zugewcheckobject").
As i understand an objectstorage just contains references to its corresponding objects, not the objects themselfs, negating any changes that were made to them in the view.
In short: How can i also pass the corresponding objectstorage objects to the updateAction in one go for them to be persisted?
Edit4: It also doesn't seem to work with that solution...
<f:form action="update" name="kaufmnnisch" object="{kaufmnnisch}" >
<f:for each="{kaufmnnisch.zugewCheckobject}" as="chk" key="chkIndex" >
<f:form.hidden property="zugewCheckobject.{chkIndex}.__identity" value="{chk.uid}" />
<f:form.checkbox property="zugewCheckobject.{chkIndex}.checked" value="{chk.checked}" /><br />
</f:for>
<f:render partial="Kaufmnnisch/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:form.submit value="Save" />
</f:form>
The problem was solved here: TYPO3 extension thought experiment: Editing a news entry and the comment entries in one go?
I am trying to add an extension attribute to a quote through a custom REST API, and I would like to retrieve this info later.
But when I try to get the value, is always null.
The code will explain better than me.
etc/di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
[...]
<preference for="Wow\Orderplatform\Api\Data\CartInterface"
type="Wow\Orderplatform\Model\Cart" />
</config>
etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\CartInterface">
<attribute code="order_platform" type="Wow\Orderplatform\Api\Data\CartInterface"/>
</extension_attributes>
</config>
CartInterface
interface CartInterface extends ExtensibleDataInterface
{
const ORDER_PLATFORM = 'order_platform';
/**
* Retrieve order platform
*
* #return string
*/
public function getOrderPlatform();
/**
* Set order platform
*
* #param string $orderPlatform
* #return $this
*/
public function setOrderPlatform($orderPlatform);
}
The implementation:
class Cart extends AbstractExtensibleModel implements CartInterface
{
/**
* {inheritdoc}
*/
public function getOrderPlatform()
{
return $this->getData(self::ORDER_PLATFORM);
}
/**
* {inheritdoc}
*/
public function setOrderPlatform($orderPlatform)
{
return $this->setData(self::ORDER_PLATFORM, $orderPlatform);
}
}
I try to save the extension attribute in a REST API:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$platformExt = $this->wowCartExtInterfaceFactory->create();
$platformExt->setOrderPlatform($platform);
$extensions->setOrderPlatform($platformExt);
$quote->setExtensionAttributes($extensions);
$this->quoteRepository->save($quote);
No errors in this procedure.
The problem is that I am not able to get back the value from the quote:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$extensions->getOrderPlatform(); // Always null
Any hints?
Thanks
This is core bug in magento2 tried to do same for some requirement and found
Join extension attributes are not adding to quote results
There seems to be an issue with join extension attributes as per my debugging
ex.
<extension_attributes for="Magento\Quote\Api\Data\CartItemInterface">
<attribute code="original_catalog_price" type="Magento\NegotiableQuote\Api\Data\NegotiableQuoteItemInterface" >
<join reference_table="negotiable_quote_item" reference_field="quote_item_id" join_on_field="item_id">
<field>original_catalog_price</field>
</join>
</attribute>
</extension_attributes>
Hopefully, the patch will release soon.
I have a component declared as:
<ipojo>
<component classname="HelloClass" name="helloCom" immediate="true">
<requires field="delayService" id="id1">
</requires>
</component>
<instance component="helloCom" name="hello">
<property name="requires.from">
<property name="id1" value="A"/>
</property>
</instance>
</ipojo>
The jar file of this component :helloComponent.jar
Now, i want to update (value="A") to (value="AA"). Thus, i implement a component using ConfigurationAdmin to update this property
public class ControllerReconfiguration {
private ConfigurationAdmin m_configAdmin;
#SuppressWarnings({ "rawtypes", "unchecked" })
public void reconfigure() throws IOException {
Configuration configuration = m_configAdmin.getConfiguration("hello","file:./helloComponent.jar");
configuration.setBundleLocation("file:./helloComponent.jar");
Properties props = new Properties();
//Dictionary props = new Hashtable();
props.put("id1", "AA");
configuration.update(props);
System.out.println("Update");
}
}
However, this ControllerReconfiguration component can't update the value 'A' (by 'AA') in 'hello' instance.
How to modify this ControllerReconfiguration component, please ?
Thanks you for your help.
Unfortunately, you can't push new 'from' configuration like this.
However, you can use the iPOJO introspection API directly: http://felix.apache.org/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/using-ipojo-introspection-api.html
Retrieve the Architecture service of the instance
Retrieve the InstanceDescription and DependencyDescription
Call the setFilter method
Thanks Clement,
it works fine !!!!! :) I access InstanceManager using Factory.
Ex, in order to access InstanceManager of component "hello.call.CallHello"
#require
private Factory[] factories;
for (Factory factory : factories) {
/*
* "hello.call.CallHello" is a component name
* note: it is not component instance name
*/
if (factory.getName().equals("hello.call.CallHello")) {
/*
* a component can have many instances
* if there is only one instance.
* get(0) return the first instance.
*/
InstanceManager im = (InstanceManager) factory.getInstances().get(0);
}
I am new to spring batch so appreciate the help. So far I have two spring batch jobs. Both of them have an item reader(sqls select) and an item writer(sql insert).
They look like this...
<job id="job-daily-tran-counts" xmlns="http://www.springframework.org/schema/batch">
<step id="job-daily-tran-counts-step1">
<tasklet>
<chunk
reader="dailyTranCountJdbcCursorItemReader"
writer="dailyTranCountItemWriter"
commit-interval="1000" />
</tasklet>
</step>
</job>
Now I want to write a simple batch job to execute a method inside one of my managers which refreshes the cache of a number of list of value maps. An item reader and item writer does not really fit in I think. How should I structure this batch job?
To be more specific I have a class named LovManagerImpl and I need to execute the afterPropertiesSet method from spring batch. What's the best way to do that?
public class LovManagerImpl implements LovManager,InitializingBean {
/**
* The list of values data access object factory
*/
#Autowired
public LovDaoFactory lovDaoFactory;
/* (non-Javadoc)
* #see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws ReportingManagerException {
Map<String,LovDao> lovDaoMap = lovDaoFactory.getLovDaoMap();
for (Map.Entry<String,LovDao> entry : lovDaoMap.entrySet()){
String code = (String)entry.getKey();
LovDao dao = (LovDao)entry.getValue();
dao.getLov(code);
}
}
thanks
Use a Tasklet; please refer to Can we write a Spring Batch Job Without ItemReader and ItemWriter answer.
For your specific case - reuse of existing service method - use a MethodInvokingTaskletAdapter.
I use Acceleo in order to generate code with a model I have made. I managed to protect my methods in order to protect them usinig "#generated NOT" in case I need to regenerate my code with Acceleo. The problem is that adding #generated NOT protect all the method content, that is to say the body, the signature and JavaDocs.
The thing is that I only need to keep the method body, or at least the method body and its signature, but I need the doc to be updated. How can I do this ?
Just for information here is an example of a potential generated class :
/*
* #generated
*/
public class ActeurRefEntrepriseServicesImpl implements ActeurRefEntrepriseServices {
#Autowired
HelloWorldService helloWorldService;
/**
* Service which say hello
*
* #param name
* user name
* #return print Hello username
*
* #generated NOT
*/
#Override
public void sayHello(final String name) {
helloWorldService.print(name);
}
}
Baptiste,
The #generated tags use the standard EMF protection rules : "#generated" means that the body of the block for which it is set will be generated, anything else means no re-generation. If you set something as "#generated" in any of your metamodels' generated code, you will see that there, too, the javadoc is preserved whatever the edits you do.
In short, you cannot tell EMF to re-generate anything other than the code itself.
If you need to have the body protected but not the javadoc, you have to shift from the "#generated" protection to Acceleo's [protected] blocks. i.e, change your template from :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
* #generated
*/
[generateSignature(methodName)/] {
[generateBody()/]
}
[/template]
to something using a protected block :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
*/
[protected (methodName)]
[generateSignature(methodName)/] {
[generateBody()/]
}
[/protected]
[/template]
With this paradigm, anything that is outside of the protected area will be regenerated, everything else will remain untouched by a regeneration.
See also the full documentation available from the Acceleo website.
If you absolutely need to use the "#generated" protection method for your model, you will need to tamper with the JMerger API from EMF and alter the launcher Acceleo generated for you in order to use your own merging strategy (see the getGenerationStrategy method from that launcher). Note that this is by no means an easy task.