How does the parameter of the extension point "org.eclipse.ui.handlers" work? - eclipse

I define an extension
<extension point="org.eclipse.ui.handlers">
<handler commandId="com.abc.test.command">
<class class="com.abc.test.TestHandler">
<parameter
name="a"
value="111">
</parameter>
</class>
</handler>
</extension>
TestHandler
public class TestHandler extends AbstractHandler {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
Map parameters = event.getParameters() ;
return null;
}
}
When TestHandler.execute(ExecutionEvent) is called, the parameters is empty.
Why? How does it work ?

The ExecutionEvent.getParameters method returns the parameters defined using the commandParameter element of the org.eclipse.ui.commands extension point defining the command.
For example:
<extension
point="org.eclipse.ui.commands">
<command
categoryId="org.eclipse.ui.category.window"
defaultHandler="org.eclipse.help.ui.internal.handlers.OpenBundleResourceHandler"
description="%command.openBundleResource.description"
id="org.eclipse.ui.browser.openBundleResource"
name="%command.openBundleResource.name">
<commandParameter
id="plugin"
name="%commandParameter.openBundleResource.plugin.name"
optional="true"/>
<commandParameter
id="path"
name="%commandParameter.openBundleResource.path.name"
optional="true"/>
</command>
</extension>
The parameter element of org.eclipse.ui.handlers is only available to the class implementing the handler if it implements the IExecutableExtension interface. This has the single method:
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException;
This gives the class access to the handler configuration element. In addition the parameter values are passed in the data object which will be a java.util.Hashtable containing the name, value pairs.
#Override
public void setInitializationData(IConfigurationElement config, String propertyName, Object data)
throws CoreException
{
if (data instanceof Hashtable<?, ?> table) {
var value = table.get("a");
}
}

Related

GWT.create vs new operator alternative

I have to use parametric constructor of my class in GWT.create, but GWT only calls default constructor. I was thinking to replace call of GWT.create with call to new Class(arguments list). Is it the right way to code in GWT deferred binding.
Code is below:
public interface ProductSelectorMetaFactory extends BeanFactory.MetaFactory {
BeanFactory<ProductSelectorTile> getProductSelectorTileFactory();
}
public CustomTileGrid(DataSource cardViewDataSource, ProductSelectorTile tileType, String fieldState,
List<DetailViewerField> list) {
setDataSource(cardViewDataSource);
setAutoFetchData(true);
GWT.create(ProductSelectorMetaFactory.class);
setTileConstructor(tileType.getClass().getName());
}
Here I want to use parameter constructor of ProductSelectorTile class. How can I use this.
Any help is appreciated.
I might be not good in explaining my current problem but feel free if you have any doubt to understand this question.
I would use a helper class with no parameters that can be created by GWT.create(). That helper class can have different implementations - the same as your original class (with parameters). Now, each implementation of helper class can create a proper instance of the original class.
Let's assume that you need different implementations for each user agent. In <module>.gwt.xml you would have this (see documentation):
<replace-with class="<module.path>.MyClassHelperGecko">
<when-type-is class="<module.path>.MyClassHelper" />
<when-property-is name="user.agent" value="gecko1_8" />
</replace-with>
<replace-with class="<module.path>.MyClassHelperSafari">
<when-type-is class="<module.path>.MyClassHelper" />
<when-property-is name="user.agent" value="safari" />
</replace-with>
...
The helper class and its implementations:
public class MyClassHelper {
MyClassInterface getInstance(String param) {
return null;
};
}
public class MyClassHelperGecko extends MyClassHelper {
#Override
public MyClassInterface getInstance(String param) {
return new MyClassGecko(param);
}
}
public class MyClassHelperSafari extends MyClassHelper {
#Override
public MyClassInterface getInstance(String param) {
return new MyClassSafari(param);
}
}
...
And finally implementations of the base class:
public interface MyClassInterface {
// ...
}
public class MyClassGecko implements MyClassInterface {
public MyClassGecko(String param) {
Window.alert("Gecko implementation; param = " + param);
// ...
}
}
public class MyClassSafari implements MyClassInterface {
public MyClassSafari(String param) {
Window.alert("Safari implementation; param = " + param);
// ...
}
}
...
Use it like this and you will see different alerts for different user-agents:
MyClassHelper helper = GWT.create(MyClassHelper.class);
helper.getInstance("abc");
This is a general Deferred Binding Using Replacement solution. There is also Deferred Binding using Generators method. Once you get the idea you can choose the method that is best for you.

struts2-rest-plugin - Pass Json object in POST method [duplicate]

I'm using this as a reference to create a REST only configuration on Struts2:
https://cwiki.apache.org/confluence/display/WW/REST+Plugin
I have one model, Receipt with a few test fields: title, body.
Currently to create a receipt, I send a request in this way:
POST /receipt/?body=new_body&title=new_title
and it creates me a receipt with the new body and title passed in.
This doesn't work:
POST /receipt/
{
"body": "new_body",
"title": "new title"
}
Here's some code:
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="jackson" class="org.apache.struts2.rest.handler.JacksonLibHandler"/>
<constant name="struts.rest.handlerOverride.json" value="jackson"/>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.rest.content.restrictToGET" value="false"/>
<constant name="struts.rest.defaultExtension" value="json"/>
<constant name="struts.rest.handlerOverride.EXTENSION" value="json"/>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.action.extension" value="xhtml,,xml,json,action"/>
<constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper" />
<constant name="struts.mapper.prefixMapping" value="/receipt:rest,:struts"/>
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="receipto"/>
<constant name="struts.convention.package.locators" value="controllers,actions"/>
</struts>
ReceiptController.java:
public class ReceiptController implements ModelDriven<Object> {
private ReceiptManager receiptManager = new ReceiptManager();
private String id;
private Receipt model = new Receipt();
private Collection list;
public Object getModel()
{
return (list==null ? model : list);
}
public HttpHeaders create()
{
receiptManager.save(model);
return new DefaultHttpHeaders("create");
}
public HttpHeaders show()
{
model = receiptManager.find(id);
return new DefaultHttpHeaders("show");
}
public HttpHeaders update()
{
receiptManager.save(model);
return new DefaultHttpHeaders("update");
}
public HttpHeaders destroy()
{
model = receiptManager.destroy(id);
return new DefaultHttpHeaders("destroy");
}
public HttpHeaders index()
{
list = receiptManager.list();
return new DefaultHttpHeaders("index").disableCaching();
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
}
Is it supposed to work as I want it to, or is it just how the plugin works?
I guess that postman is sending JSON in the body of the request and sets the content type application/json. Struts can parse the request if you add json interceptor to the stack.
<interceptor-stack name="myStack">
<interceptor-ref name="json"/>
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
The description for "json" interceptor in the JSON Plugin:
If the interceptor is used, the action will be populated from the JSON content in the request, these are the rules of the interceptor:
The "content-type" must be "application/json"
The JSON content must be well formed, see json.org for grammar.
Action must have a public "setter" method for fields that must be populated.
Supported types for population are: Primitives (int,long...String), Date, List, Map, Primitive Arrays, Other class (more on this later), and Array of Other class.
Any object in JSON, that is to be populated inside a list, or a map, will be of type Map (mapping from properties to values), any whole number will be of type Long, any decimal number will be of type Double, and any array of type List.
Resources:
Kickstart FAQ
Getting Started
FAQs
Other Resources

Using MultiResourceItemReader to read 2 plain text file and write into single file

My batch job will generate 2 text files with string format per line. I created a reader
<bean id="myMultiResourceReader"
class=" org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="file:D:/MY/sample/*.txt" />
</bean>
<bean id="myFinalWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
scope="step">
<property name="resource" value="${test.file3}" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="footerCallback" ref="myFinalCustomItemWriter" />
<property name="headerCallback" ref="myFinalCustomItemWriter" />
</bean>
<bean id="myFinalCustomItemWriter" class="my.process.MyWriter"
scope="step">
<property name="delegate" ref="myFinalWriter" />
<property name="stepContext" value="#{stepExecution.stepName}" />
</bean>
I was getting this error:
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.FlatFileItemWriter' for property 'delegate'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found
Basically I just want to combine two plain file, and append the total count at footer. Then delete away the both input file. Can help?
MyWriter.java
public class MyWriter implements ItemWriter<String>, FlatFileFooterCallback, FlatFileHeaderCallback, ItemStream{
private static Logger log = Logger.getLogger(MyWriter.class);
private FlatFileItemWriter<String> delegate;
private int recordCount = 0;
private String stepContext;
public void writeFooter(Writer writer) throws IOException {
writer.write("#" + recordCount);
}
public void writeHeader(Writer writer) throws IOException {
writer.write("#" + StringUtil.getSysDate());
}
public void setDelegate(FlatFileItemWriter<String> delegate) {
this.delegate = delegate;
}
public void write(List<? extends String> list) throws Exception {
int chunkRecord = 0;
for (String item : list) {
chunkRecord++;
}
delegate.write(list);
recordCount += chunkRecord;
}
public void close() throws ItemStreamException {
this.delegate.close();
}
public void open(ExecutionContext arg0) throws ItemStreamException {
this.delegate.open(arg0);
}
public void update(ExecutionContext arg0) throws ItemStreamException {
this.delegate.update(arg0);
}
public void setStepContext(String stepContext) {
this.stepContext = stepContext;
}
}
As Luca Basso Ricci already pointed out, the problem is your delegate definition in MyWriter. Since Spring creates proxies for it beans, it will not recognize your FlatFileItemReader as an actual instance of FlatFileItemWriter and, therefore, the setDelegate(FlatFileItemWriter delegate) will fail.
Use an ItemStreamWriter in MyWriter. As you see in the exception message, the created proxy does provide this interface. Hence, it can be inserted
This will solve the delegation to write, open, close, and update method. In order to write the header and footer, you need to implement a HeaderCallback and FooterCallback and set it directly in the definition of your FlatFileItemWriter.
Implementing the HeaderCallback is not a problem since you only set the systemdate.
As FooterCallback, make your own Bean. Use it in the FlatFileItemWriter to write the footer. Add an "increaseCount" method to it and use it in your MyWriter Bean to increase the written count.
public void write(List<? extends String> list) throws Exception {
myFooterCallback.increaseCount(list.size());
delegate.write(list);
}
Another possible option would be to directly extend MyWriter from FlatFileItemWriter:
public class MyWriter extends FlatFileItemWriter<String> implements FlatFileFooterCallback, FlatFileHeaderCallback{
private static Logger log = Logger.getLogger(MyWriter.class);
private int recordCount = 0;
private String stepContext;
public void writeFooter(Writer writer) throws IOException {
writer.write("#" + recordCount);
}
public void writeHeader(Writer writer) throws IOException {
writer.write("#" + StringUtil.getSysDate());
}
public void afterPropertiesSet() {
setFooterCallback(this);
setHeaderCallback(this);
super.afterPropertiesSet();
}
public void write(List<? extends String> list) throws Exception {
super.write(list);
recordCount += list.size();
}
}
Configuration in your XML would look like this:
<bean id="myFinalCustomItemWriter" class="my.process.MyWriter" scope="step">
<property name="resource" value="${test.file3}" />
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="stepContext" value="#{stepExecution.stepName}" />
</bean>

Adding Menu Button Eclipse Plugin

I added a main menu button for an eclipse plugin, and this code was generated to handle the action when the button is pressed:
package de.vogella.plugin.experiment;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.handlers.HandlerUtil;
public class SomethingHandler implements IHandler {
#Override
public void addHandlerListener(IHandlerListener handlerListener) {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
System.out.println("Hello");
// TODO Auto-generated method stub
return null;
}
#Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isHandled() {
// TODO Auto-generated method stub
return false;
}
#Override
public void removeHandlerListener(IHandlerListener handlerListener) {
// TODO Auto-generated method stub
}
}
I added the print statement in the execute class to test to see if anything would happen when I pressed the button. However, when I run this plugin as an eclipse application, and press the button, the button stays pressed until I click it again, and nothing else happens. How can I execute some event when I press the button? And then have the process complete so I don't have to press the button again to turn it off?
EDIT:
Here is my plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
>
<extension
point="org.eclipse.ui.commands">
<command
defaultHandler="de.vogella.plugin.experiment.SomethingHandler"
id="de.vogella.plugin.experiment.SomethingHandler"
name="name">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="SomethingHandler"
commandId="de.vogella.plugin.experiment.SomethingHandler">
</handler>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.ui.main.menu">
<command
commandId="de.vogella.plugin.experiment.SomethingHandler"
label="DoSomething"
style="push">
</command>
</menuContribution>
</extension>
</plugin>
The menuContribution you have is just defining the top level menu item which doesn't work like a normal push button. You need to define a menu to appear in the drop down list for the menu. Something like:
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.ui.main.menu">
<menu
id="menu.id"
label="Top Level Menu">
<command
commandId="de.vogella.plugin.experiment.SomethingHandler"
label="DoSomething"
style="push">
</command>
</menu>
</menuContribution>
</extension>

custom submenu won't react on click

I am trying to implement an extension in JDeveloper. It creats a submenu when you click on a DB package.
THe issue comes when I click on an element of my custom submenu, it returns a null pointer Exception.
I can't figure out where I did wrong.
Would you please help me?
Here is how a I created the submenu:
submenu.xml File:
<?xml version="1.0" encoding="windows-1252" ?>
<!-- usage of a name space?-->
<items id="my.contextMenu">
<folder type="PACKAGE">
<name>User Defined Context Menu</name>
<item reloadparent="true"
action-ref="utilitytools.customSave">
<title>saveThisPackage</title>
</folder>
</items>
extension.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<extension id="utilitytools" version="1.0" esdk-version="1.0"
rsbundle-class="utilitytools.Res"
xmlns="http://jcp.org/jsr/198/extension-manifest">
<name>Utility Tools</name>
<owner>A name</owner>
<dependencies>
<import>oracle.sqldeveloper</import>
<import>oracle.ide</import>
</dependencies>
<hooks>
<jdeveloper-hook xmlns="http://xmlns.oracle.com/jdeveloper/1013/extension">
<addins>
<addin>utilitytools.UtilityToolsAddin</addin>
</addins>
<actions xmlns="http://xmlns.oracle.com/jdeveloper/1013/extension">
<action id="utilitytools.customSave">
<properties>
<property name="Name">saveThisPackage</property>
<property name="SmallIcon"></property>
<property name="LongDescription"></property>
</properties>
<controller-class>utilitytools.savePackageController</controller-class>
<command-class>utilitytools.savePackageCommand</command-class>
</action>
</actions>
</jdeveloper-hook>
<sqldev-navigator-hook xmlns="http://xmlns.oracle.com/sqldeveloper/sqldev-navigator">
<descriptor>submenu.xml</descriptor>
</sqldev-navigator-hook>
</hooks>
</extension>
SubmenuListener file:
public final class SubMenuListener implements ContextMenuListener {
public SubMenuListener() {
super();
}
public void menuWillShow(ContextMenu contextMenu) {
contextMenu.add( contextMenu.createMenuItem(
IdeAction.find( savePackageCommand.actionId() )
));
}
public void menuWillHide(ContextMenu contextMenu) {
//Nothing
}
public boolean handleDefaultAction(Context context) {
return false;
}
}
And the command file:
/**
* Command handler for utilitytools.customSave.
*/
#RegisteredByExtension("utilitytools")
public final class sauvegardePackageCommand extends Command {
public savePackageCommand() {
super(actionId());
}
public int doit() {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
showSaveWindow();
}
});
return OK;
}
/**
* Returns the id of the action this command is associated with.
*
* #return the id of the action this command is associated with.
* #throws IllegalStateException if the action this command is associated
* with is not registered.
*/
public static int actionId() {
final Integer cmdId = Ide.findCmdID(".utilitytools.customSave");
if (cmdId == null)
throw new IllegalStateException("Action esdksample.showElementClass not found.");
return cmdId;
}
private static void showSaveWindow(){
JFrame frame = new JFrame("SAVE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JPanelSavePackage());//Or any window you want to popup
frame.pack();
frame.setVisible(true);
}
}