[299086] EJB Timer wizard
diff --git a/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
index 22bf239..eb33eaf 100644
--- a/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
@@ -47,4 +47,5 @@
  org.eclipse.jst.jee.ui;bundle-version="[1.0.100,2.0.0)"
 Eclipse-LazyStart: true
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Import-Package: org.eclipse.emf.codegen.jet
 Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/util/EJBUIMessages.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/util/EJBUIMessages.java
index f073689..6a3839f 100644
--- a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/util/EJBUIMessages.java
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/util/EJBUIMessages.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Oracle - EJB Timer
  *******************************************************************************/
 package org.eclipse.jst.ejb.ui.internal.util;
 
@@ -107,7 +108,11 @@
 	public static String REMOTE_COMPONENT_INTERFACE_TOOLTIP;
 	public static String REMOTE_HOME_INTERFACE_TOOLTIP;
 	public static String EJB_CLIENT_JAR_GROUP;
-	
+
+	//EJB Timer
+    public static String timerWizardTitle;
+    public static String timerWizardDescription;
+    public static String timerScheduleLabel;
 
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, EJBUIMessages.class);
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizard.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizard.java
new file mode 100644
index 0000000..d9173a8
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizard.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ludovic Champenois ludo@java.net
+ *******************************************************************************/
+
+package org.eclipse.jst.ejb.ui.internal.wizard;
+
+import org.eclipse.jst.ejb.ui.internal.util.EJBUIMessages;
+import org.eclipse.jst.j2ee.ejb.internal.operations.AddEjbTimerDataModelProvider;
+import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider;
+
+@SuppressWarnings("restriction")
+/* 
+ * Java EE 6 EJB Timer wizard
+ */
+public class AddEjbTimerWizard extends NewEnterpriseBeanWizard {
+
+	public AddEjbTimerWizard() {
+		this(null);
+	}
+
+	public AddEjbTimerWizard(IDataModel model) {
+		super(model);
+		setWindowTitle(EJBUIMessages.timerWizardTitle);
+	}
+
+	@Override
+	protected void doAddPages() {
+		AddEjbTimerWizardPage page1 = new AddEjbTimerWizardPage(getDataModel(),
+				"page1", EJBUIMessages.timerWizardDescription, //$NON-NLS-1$
+				EJBUIMessages.timerWizardTitle, J2EEProjectUtilities.EJB);
+		addPage(page1);
+	}
+
+	@Override
+	protected IDataModelProvider getDefaultProvider() {
+		return new AddEjbTimerDataModelProvider();
+	}
+}
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizardPage.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizardPage.java
new file mode 100644
index 0000000..ec43328
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/AddEjbTimerWizardPage.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ludovic Champenois ludo@java.net
+ *******************************************************************************/
+
+
+package org.eclipse.jst.ejb.ui.internal.wizard;
+
+import org.eclipse.jst.ejb.ui.internal.util.EJBUIMessages;
+import org.eclipse.jst.j2ee.ejb.internal.operations.AddEjbTimerDataModelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+@SuppressWarnings("restriction")
+/* 
+ * Java EE 6 EJB Timer wizard page
+ */
+public class AddEjbTimerWizardPage extends NewEnterpriseBeanClassWizardPage {
+
+	private Text scheduleText;
+
+	public AddEjbTimerWizardPage(IDataModel mode, String pageName,
+			String pageDesc, String pageTitle, String moduleType) {
+		super(mode, pageName, pageDesc, pageTitle, moduleType);
+	}
+
+	@Override
+	protected Composite createTopLevelComposite(Composite parent) {
+		Composite composite = super.createTopLevelComposite(parent);
+
+		addSeperator(composite, 3);
+		
+		new Label(composite, SWT.LEFT).setText(EJBUIMessages.timerScheduleLabel);
+		scheduleText = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.WRAP /*| SWT.V_SCROLL*/);
+		GridData layoutData = new GridData(GridData.FILL_BOTH);
+		layoutData.verticalSpan = 2;
+		initializeDialogUnits(scheduleText);
+		layoutData.heightHint = convertHeightInCharsToPixels(2);
+		scheduleText.setLayoutData(layoutData);
+		synchHelper.synchText(scheduleText,
+				AddEjbTimerDataModelProvider.SCHEDULE, null);
+
+		return composite;
+	}
+	
+	@Override
+	protected String[] getValidationPropertyNames() {
+		String[] base = super.getValidationPropertyNames();
+		String[] result = new String[base.length + 1];
+		System.arraycopy(base, 0, result, 0, base.length);
+		result[base.length] = AddEjbTimerDataModelProvider.SCHEDULE;
+		return result;
+	}
+
+
+}
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/IEjbWizardConstants.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/IEjbWizardConstants.java
index 07a8e73..c3d40fc 100644
--- a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/IEjbWizardConstants.java
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/wizard/IEjbWizardConstants.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  * Kaloyan Raev, kaloyan.raev@sap.com - initial API and implementation
+ * Ludovic Champenois ludo@java.net
  *******************************************************************************/
 package org.eclipse.jst.ejb.ui.internal.wizard;
 
@@ -48,4 +49,8 @@
 	public static final String MESSAGE_LISTENER_INTERFACE_HYPERLINK_TOOLTIP = EJBUIMessages.MESSAGE_LISTENER_INTERFACE_HYPERLINK_TOOLTIP;
 	public static final String CLICK_TO_SELECT = EJBUIMessages.CLICK_TO_SELECT;
 	
+    public static final  String timerWizardTitle = EJBUIMessages.timerWizardTitle;
+    public static final  String timerWizardDescription = EJBUIMessages.timerWizardDescription;
+    public static final  String timerScheduleLabel = EJBUIMessages.timerScheduleLabel;
+	
 }
diff --git a/plugins/org.eclipse.jst.ejb.ui/plugin.properties b/plugins/org.eclipse.jst.ejb.ui/plugin.properties
index 3ae4554..bded88e 100644
--- a/plugins/org.eclipse.jst.ejb.ui/plugin.properties
+++ b/plugins/org.eclipse.jst.ejb.ui/plugin.properties
@@ -7,6 +7,7 @@
 #
 # Contributors:
 #     IBM Corporation - initial API and implementation
+#     Oracle - EJB Timer
 ###############################################################################
 providerName=Eclipse.org
 pluginName=WTP EJB UI Plug-in
@@ -103,3 +104,7 @@
 BeanWebRegionWizard.description=Create a new EJB 3.x Session Bean
 MDBEjbRegionWizard.name=Message-Driven Bean (EJB 3.x)
 MDBEjbRegionWizard.description=Create a new EJB 3.x Message-Driven Bean
+
+
+EJBTIMER.ejbtimerlabel=EJB Timer (Java EE 6)
+EJBTIMER.ejbtimer.BeanWebRegionWizard.description=Create a new Java EE 6 EJB Timer
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.ejb.ui/plugin.xml b/plugins/org.eclipse.jst.ejb.ui/plugin.xml
index 6a6e9a5..ff92688 100644
--- a/plugins/org.eclipse.jst.ejb.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.ejb.ui/plugin.xml
@@ -82,6 +82,30 @@
             %MDBEjbRegionWizard.description
          </description>
       </wizard>
+      
+       <wizard
+             category="org.eclipse.jst.ejb.ui"
+             class="org.eclipse.jst.ejb.ui.internal.wizard.AddEjbTimerWizard"
+             icon="icons/full/ctool16/sessionbean_wiz.gif"
+             id="org.eclipse.jst.ejb.ui.internal.wizard.AddEjbTimerWizard"
+             name="%EJBTIMER.ejbtimerlabel">
+		 <class
+               class="org.eclipse.jst.ejb.ui.internal.wizard.AddEjbTimerWizard">
+            <parameter
+                  name="javaeeartifact"
+                  value="true">
+            </parameter>
+            <parameter
+                  name="menuIndex"
+                  value="37">
+            </parameter>
+         </class>
+         <description>
+            %EJBTIMER.ejbtimer.BeanWebRegionWizard.description
+         </description>
+       </wizard>      
+      
+      
    </extension>
 <!-- Navigator Object Contributions -->
 <!-- EJB Group Contributions 
diff --git a/plugins/org.eclipse.jst.ejb.ui/property_files/ejb_ui.properties b/plugins/org.eclipse.jst.ejb.ui/property_files/ejb_ui.properties
index 6ca7ffc..6b4781c 100644
--- a/plugins/org.eclipse.jst.ejb.ui/property_files/ejb_ui.properties
+++ b/plugins/org.eclipse.jst.ejb.ui/property_files/ejb_ui.properties
@@ -7,6 +7,7 @@
 #
 # Contributors:
 # IBM Corporation - initial API and implementation
+# Oracle - EJB Timer
 ###############################################################################
 KEY_0=Failed to find the image "{0}".
 KEY_1=New EJB Project
@@ -91,4 +92,8 @@
 MESSAGE_LISTENER_INTERFACE_HYPERLINK=Message &listener: 
 MESSAGE_LISTENER_INTERFACE_HYPERLINK_TOOLTIP=Set message listener interface
 CLICK_TO_SELECT=<click to select>
-EJB_CLIENT_JAR_GROUP=EJB Client JAR
\ No newline at end of file
+EJB_CLIENT_JAR_GROUP=EJB Client JAR
+
+timerWizardTitle=Create EJB Timer Callback
+timerWizardDescription=Create Java class with an added EJB Timer Callback method.
+timerScheduleLabel=Schedule: 
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerClassOperation.java b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerClassOperation.java
new file mode 100644
index 0000000..7a4c3d0
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerClassOperation.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ludovic Champenois ludo@java.net
+ *******************************************************************************/
+
+package org.eclipse.jst.j2ee.ejb.internal.operations;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.codegen.jet.JETException;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.internal.enablement.nonui.WFTWrappedException;
+
+@SuppressWarnings("restriction")
+public class AddEjbTimerClassOperation extends NewEnterpriseBeanClassOperation {
+
+	/**
+	 * folder location of the EJB Timer creation templates directory
+	 */
+	protected static final String TEMPLATE_FILE = "/templates/ejbtimer.javajet"; //$NON-NLS-1$
+
+	public AddEjbTimerClassOperation(IDataModel dataModel) {
+		super(dataModel);
+	}
+
+	@Override
+	protected void generateUsingTemplates(IProgressMonitor monitor,
+			IPackageFragment fragment) throws WFTWrappedException,
+			CoreException {
+		// Create the enterprise bean template model
+		AddEjbTimerTemplateModel tempModel = new AddEjbTimerTemplateModel(model);
+		// Using the WTPJetEmitter, generate the java source based on the bean
+		// template model
+		try {
+			if (fragment != null) {
+				// Create the EJB Timer java file
+				EjbTimerTemplate tempImpl = EjbTimerTemplate.create(null);
+
+				try {
+					Method method = tempImpl.getClass().getMethod("generate", //$NON-NLS-1$
+							new Class[] { Object.class });
+					String source = (String) method.invoke(tempImpl, tempModel);
+					String javaFileName = tempModel.getClassName() + ".java"; //$NON-NLS-1$
+					createJavaFile(monitor, fragment, source, javaFileName);
+				} catch (SecurityException e) {
+					throw new JETException(e);
+				} catch (NoSuchMethodException e) {
+					throw new JETException(e);
+				} catch (IllegalArgumentException e) {
+					throw new JETException(e);
+				} catch (IllegalAccessException e) {
+					throw new JETException(e);
+				} catch (InvocationTargetException e) {
+					throw new JETException(e);
+				}
+			}
+		} catch (Exception e) {
+			throw new WFTWrappedException(e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerDataModelProvider.java b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerDataModelProvider.java
new file mode 100644
index 0000000..5614f37
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerDataModelProvider.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ludovic Champenois ludo@java.net
+ *******************************************************************************/
+
+
+package org.eclipse.jst.j2ee.ejb.internal.operations;
+
+import static org.eclipse.jst.j2ee.ejb.internal.operations.INewEnterpriseBeanClassDataModelProperties.EJB_NAME;
+
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassDataModelProvider;
+import org.eclipse.jst.j2ee.internal.common.operations.NewJavaEEArtifactClassOperation;
+import org.eclipse.jst.j2ee.internal.ejb.project.operations.EJBCreationResourceHandler;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider;
+import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;
+
+
+@SuppressWarnings("restriction")
+public class AddEjbTimerDataModelProvider extends
+		NewEnterpriseBeanClassDataModelProvider {
+
+	public static final String SCHEDULE = "AddEjbTimer.SCHEDULE"; //$NON-NLS-1$
+
+	@Override
+	public IDataModelOperation getDefaultOperation() {
+		return new AddEnterpriseBeanOperation(getDataModel()) {
+
+			@Override
+			protected NewJavaEEArtifactClassOperation getNewClassOperation() {
+				return new AddEjbTimerClassOperation(getDataModel());
+			}
+		};
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own data model's
+	 * properties as valid base properties.
+	 * 
+	 * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider#getPropertyNames()
+	 */
+	@Override
+	public Set<String> getPropertyNames() {
+		// Add Bean specific properties defined in this data model
+		Set<String> propertyNames = super.getPropertyNames();
+
+		propertyNames.add(SCHEDULE);
+
+		return propertyNames;
+	}
+
+	/**
+	 * Subclasses may extend this method to provide their own default values for
+	 * any of the properties in the data model hierarchy. This method does not
+	 * accept a null parameter. It may return null.
+	 * 
+	 * @see NewJavaClassDataModelProvider#getDefaultProperty(String)
+	 * @see IDataModelProvider#getDefaultProperty(String)
+	 * 
+	 * @param propertyName
+	 * @return Object default value of property
+	 */
+	@Override
+	public Object getDefaultProperty(String propertyName) {
+		if (propertyName.equals(SCHEDULE)) {
+			return EJBCreationResourceHandler.timerScheduleDefault;
+		}
+		
+		// Otherwise check super for default value for property
+		return super.getDefaultProperty(propertyName);
+	}
+
+	@Override
+	public IStatus validate(String propertyName) {
+		// we need to override to remove the error condition for EJB_NAME
+		if (EJB_NAME.equals(propertyName)){
+			return null;
+		}
+
+		if (SCHEDULE.equals(propertyName)) {
+			String value = (String) getProperty(SCHEDULE);
+			if (value == null || value.trim().length() == 0) {
+				return WTPCommonPlugin.createErrorStatus(EJBCreationResourceHandler.errorTimerScheduleMissing);
+			}
+		}
+		IStatus status = super.validate(propertyName);
+		return status;
+	}
+}
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerTemplateModel.java b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerTemplateModel.java
new file mode 100644
index 0000000..9e6fafb
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/AddEjbTimerTemplateModel.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ludovic Champenois ludo@java.net
+ *******************************************************************************/
+
+package org.eclipse.jst.j2ee.ejb.internal.operations;
+
+import static org.eclipse.jst.j2ee.ejb.internal.operations.INewEnterpriseBeanClassDataModelProperties.EJB_NAME;
+import static org.eclipse.jst.j2ee.ejb.internal.operations.INewEnterpriseBeanClassDataModelProperties.MAPPED_NAME;
+
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jst.j2ee.internal.common.operations.Method;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+@SuppressWarnings("restriction")
+public class AddEjbTimerTemplateModel extends CreateEnterpriseBeanTemplateModel {
+
+	public static final String QUALIFIED_SCHEDULE = "javax.ejb.Schedule"; //$NON-NLS-1$
+	public static final String QUALIFIED_TIMER = "javax.ejb.Timer"; //$NON-NLS-1$
+	public static final String QUALIFIED_STATELESS = "javax.ejb.Stateless"; //$NON-NLS-1$
+
+	public static final String SCHEDULED_TIMEOUT = "scheduledTimeout"; //$NON-NLS-1$
+
+	public AddEjbTimerTemplateModel(IDataModel adataModel) {
+		super(adataModel);
+	}
+
+	@Override
+	public Collection<String> getImports() {
+		Collection<String> collection = super.getImports();
+
+		collection.add(QUALIFIED_SCHEDULE);
+		collection.add(QUALIFIED_STATELESS);
+		collection.add(QUALIFIED_TIMER);
+
+		return collection;
+	}
+
+	public Map<String, String> getClassAnnotationParams() {
+		Map<String, String> result = new Hashtable<String, String>();
+
+		String dispName = getProperty(EJB_NAME).trim();
+		if (!dispName.equals(getClassName()) && (dispName.length() > 0)) {
+			result.put(ATT_NAME, QUOTATION_STRING + dispName + QUOTATION_STRING);
+		}
+		String mappedName = getProperty(MAPPED_NAME).trim();
+		if (mappedName != null && mappedName.length() > 0) {
+			result.put(ATT_MAPPED_NAME, QUOTATION_STRING + mappedName + QUOTATION_STRING);
+		}
+
+		return result;
+	}
+
+	@Override
+	public String getProperty(String propertyName) {
+		return dataModel.getStringProperty(propertyName);
+	}
+
+	@Override
+	public Collection<Method> getUnimplementedMethods() {
+		Collection<Method> unimplementedMethods = super
+				.getUnimplementedMethods();
+		Iterator<Method> iterator = unimplementedMethods.iterator();
+
+		while (iterator.hasNext()) {
+			Method method = iterator.next();
+			if (SCHEDULED_TIMEOUT.equals(method.getName())) {
+				iterator.remove();
+			}
+		}
+
+		return unimplementedMethods;
+	}
+
+}
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/EjbTimerTemplate.java b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/EjbTimerTemplate.java
new file mode 100644
index 0000000..e446736
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ejb/ejb/org/eclipse/jst/j2ee/ejb/internal/operations/EjbTimerTemplate.java
@@ -0,0 +1,239 @@
+package org.eclipse.jst.j2ee.ejb.internal.operations;
+
+import java.util.*;
+
+import org.eclipse.jst.j2ee.internal.common.operations.*;
+
+
+
+@SuppressWarnings("restriction")
+public class EjbTimerTemplate {
+  protected static String nl;
+  public static synchronized EjbTimerTemplate create(String lineSeparator)
+  {
+    nl = lineSeparator;
+    EjbTimerTemplate result = new EjbTimerTemplate();
+    nl = null;
+    return result;
+  }
+
+  public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl; //$NON-NLS-1$
+  protected final String TEXT_1 = "package "; //$NON-NLS-1$
+  protected final String TEXT_2 = ";"; //$NON-NLS-1$
+  protected final String TEXT_3 = NL;
+  protected final String TEXT_4 = NL + "import "; //$NON-NLS-1$
+  protected final String TEXT_5 = ";"; //$NON-NLS-1$
+  protected final String TEXT_6 = NL + NL + "@Stateless"; //$NON-NLS-1$
+  protected final String TEXT_7 = NL + "public "; //$NON-NLS-1$
+  protected final String TEXT_8 = "abstract "; //$NON-NLS-1$
+  protected final String TEXT_9 = "final "; //$NON-NLS-1$
+  protected final String TEXT_10 = "class "; //$NON-NLS-1$
+  protected final String TEXT_11 = " extends "; //$NON-NLS-1$
+  protected final String TEXT_12 = " implements "; //$NON-NLS-1$
+  protected final String TEXT_13 = ", "; //$NON-NLS-1$
+  protected final String TEXT_14 = " {"; //$NON-NLS-1$
+  protected final String TEXT_15 = NL + NL + "    /**" + NL + "     * Default constructor. " + NL + "     */" + NL + "    public "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+  protected final String TEXT_16 = "() {" + NL + "        // TODO Auto-generated constructor stub" + NL + "    }"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  protected final String TEXT_17 = NL + "       " + NL + "    /**" + NL + "     * @see "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  protected final String TEXT_18 = "#"; //$NON-NLS-1$
+  protected final String TEXT_19 = "("; //$NON-NLS-1$
+  protected final String TEXT_20 = ")" + NL + "     */" + NL + "    public "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  protected final String TEXT_21 = "("; //$NON-NLS-1$
+  protected final String TEXT_22 = ") {" + NL + "        super("; //$NON-NLS-1$ //$NON-NLS-2$
+  protected final String TEXT_23 = ");" + NL + "        // TODO Auto-generated constructor stub" + NL + "    }"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  protected final String TEXT_24 = NL + NL + "\t/**" + NL + "     * @see "; //$NON-NLS-1$ //$NON-NLS-2$
+  protected final String TEXT_25 = "#"; //$NON-NLS-1$
+  protected final String TEXT_26 = "("; //$NON-NLS-1$
+  protected final String TEXT_27 = ")" + NL + "     */" + NL + "    public "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  protected final String TEXT_28 = " "; //$NON-NLS-1$
+  protected final String TEXT_29 = "("; //$NON-NLS-1$
+  protected final String TEXT_30 = ") {" + NL + "        // TODO Auto-generated method stub"; //$NON-NLS-1$ //$NON-NLS-2$
+  protected final String TEXT_31 = NL + "\t\t\treturn "; //$NON-NLS-1$
+  protected final String TEXT_32 = ";"; //$NON-NLS-1$
+  protected final String TEXT_33 = NL + "    }"; //$NON-NLS-1$
+  protected final String TEXT_34 = NL + "\t"; //$NON-NLS-1$
+  protected final String TEXT_35 = NL + "\t@SuppressWarnings(\"unused\")" + NL + "\t@Schedule("; //$NON-NLS-1$ //$NON-NLS-2$
+  protected final String TEXT_36 = ")" + NL + "    private void scheduledTimeout(final Timer t) {" + NL + "        System.out.println(\"@Schedule called at: \" + new java.util.Date());" + NL + "    }" + NL + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+	public String generate(Object argument)
+  {
+    final StringBuffer stringBuffer = new StringBuffer();
+     AddEjbTimerTemplateModel model = (AddEjbTimerTemplateModel) argument; 
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+    
+	model.removeFlags(CreateJavaEEArtifactTemplateModel.FLAG_QUALIFIED_SUPERCLASS_NAME); 
+
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+    
+	if (model.getJavaPackageName() != null && model.getJavaPackageName().length() > 0) {
+
+    stringBuffer.append(TEXT_1);
+    stringBuffer.append( model.getJavaPackageName() );
+    stringBuffer.append(TEXT_2);
+    
+	}
+
+    stringBuffer.append(TEXT_3);
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+     
+	Collection<String> imports = model.getImports();
+	for (String anImport : imports) { 
+
+    stringBuffer.append(TEXT_4);
+    stringBuffer.append( anImport );
+    stringBuffer.append(TEXT_5);
+     
+	}
+
+    stringBuffer.append(TEXT_6);
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+    
+	if (model.isPublic()) { 
+
+    stringBuffer.append(TEXT_7);
+     
+	} 
+
+	if (model.isAbstract()) { 
+
+    stringBuffer.append(TEXT_8);
+    
+	}
+
+	if (model.isFinal()) {
+
+    stringBuffer.append(TEXT_9);
+    
+	}
+
+    stringBuffer.append(TEXT_10);
+    stringBuffer.append( model.getClassName() );
+    
+	String superClass = model.getSuperclassName();
+ 	if (superClass != null && superClass.length() > 0) {
+
+    stringBuffer.append(TEXT_11);
+    stringBuffer.append( superClass );
+    
+	}
+
+	List<String> interfaces = model.getInterfaces(); 
+ 	if ( interfaces.size() > 0) { 
+
+    stringBuffer.append(TEXT_12);
+    
+	}
+	
+ 	for (int i = 0; i < interfaces.size(); i++) {
+   		String INTERFACE = interfaces.get(i);
+   		if (i > 0) {
+
+    stringBuffer.append(TEXT_13);
+    
+		}
+
+    stringBuffer.append( INTERFACE );
+    
+	}
+
+    stringBuffer.append(TEXT_14);
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+     
+	if (!model.hasEmptySuperclassConstructor()) { 
+
+    stringBuffer.append(TEXT_15);
+    stringBuffer.append( model.getClassName() );
+    stringBuffer.append(TEXT_16);
+     
+	} 
+
+	if (model.shouldGenSuperclassConstructors()) {
+		List<Constructor> constructors = model.getConstructors();
+		for (Constructor constructor : constructors) {
+			if (constructor.isPublic() || constructor.isProtected()) { 
+
+    stringBuffer.append(TEXT_17);
+    stringBuffer.append( model.getSuperclassName() );
+    stringBuffer.append(TEXT_18);
+    stringBuffer.append( model.getSuperclassName() );
+    stringBuffer.append(TEXT_19);
+    stringBuffer.append( constructor.getParamsForJavadoc() );
+    stringBuffer.append(TEXT_20);
+    stringBuffer.append( model.getClassName() );
+    stringBuffer.append(TEXT_21);
+    stringBuffer.append( constructor.getParamsForDeclaration() );
+    stringBuffer.append(TEXT_22);
+    stringBuffer.append( constructor.getParamsForCall() );
+    stringBuffer.append(TEXT_23);
+    
+			} 
+		} 
+	} 
+
+     /* This Content is provided under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at http://www.eclipse.org/org/documents/epl-v10.php 
+For purposes of the EPL, "Program" will mean the Content. 
+
+Copied from org.eclipse.jst.j2ee.ejb plugin. */ 
+    
+	if (model.shouldImplementAbstractMethods()) {
+		for (Method method : model.getUnimplementedMethods()) { 
+
+    stringBuffer.append(TEXT_24);
+    stringBuffer.append( method.getContainingJavaClass() );
+    stringBuffer.append(TEXT_25);
+    stringBuffer.append( method.getName() );
+    stringBuffer.append(TEXT_26);
+    stringBuffer.append( method.getParamsForJavadoc() );
+    stringBuffer.append(TEXT_27);
+    stringBuffer.append( method.getReturnType() );
+    stringBuffer.append(TEXT_28);
+    stringBuffer.append( method.getName() );
+    stringBuffer.append(TEXT_29);
+    stringBuffer.append( method.getParamsForDeclaration() );
+    stringBuffer.append(TEXT_30);
+     
+			String defaultReturnValue = method.getDefaultReturnValue();
+			if (defaultReturnValue != null) { 
+
+    stringBuffer.append(TEXT_31);
+    stringBuffer.append( defaultReturnValue );
+    stringBuffer.append(TEXT_32);
+    
+			} 
+
+    stringBuffer.append(TEXT_33);
+     
+		}
+	} 
+
+    stringBuffer.append(TEXT_34);
+    
+		String schedule = model.getProperty(AddEjbTimerDataModelProvider.SCHEDULE).trim();
+	
+    stringBuffer.append(TEXT_35);
+    stringBuffer.append( schedule );
+    stringBuffer.append(TEXT_36);
+    return stringBuffer.toString();
+  }
+}
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/ejbcreation/org/eclipse/jst/j2ee/internal/ejb/project/operations/EJBCreationResourceHandler.java b/plugins/org.eclipse.jst.j2ee.ejb/ejbcreation/org/eclipse/jst/j2ee/internal/ejb/project/operations/EJBCreationResourceHandler.java
index 7daba16..a55d26b 100644
--- a/plugins/org.eclipse.jst.j2ee.ejb/ejbcreation/org/eclipse/jst/j2ee/internal/ejb/project/operations/EJBCreationResourceHandler.java
+++ b/plugins/org.eclipse.jst.j2ee.ejb/ejbcreation/org/eclipse/jst/j2ee/internal/ejb/project/operations/EJBCreationResourceHandler.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Oracle - EJB Timer
  *******************************************************************************/
 package org.eclipse.jst.j2ee.internal.ejb.project.operations;
 
@@ -167,7 +168,10 @@
 	public static String ERR_SINGLETON_NOT_ALLOWED;
 	public static String ERR_NO_INTERFACE_NOT_ALLOWED;
 
-
+	//EJB Timer specific
+    public static String timerScheduleDefault;
+    public static String errorTimerScheduleMissing;
+      
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, EJBCreationResourceHandler.class);
 	}
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/property_files/ejbcreation.properties b/plugins/org.eclipse.jst.j2ee.ejb/property_files/ejbcreation.properties
index c959797..df81386 100644
--- a/plugins/org.eclipse.jst.j2ee.ejb/property_files/ejbcreation.properties
+++ b/plugins/org.eclipse.jst.j2ee.ejb/property_files/ejbcreation.properties
@@ -151,3 +151,6 @@
 WRN_NO_CLIENT_VIEW=No client view configured. Clients will not be able to access this bean.
 ERR_SINGLETON_NOT_ALLOWED=The 'Singleton' state type is allowed only for EJB projects with version 3.1 or later.
 ERR_NO_INTERFACE_NOT_ALLOWED=The no-interface client view is allowed only for EJB projects with version 3.1 or later. 
+
+timerScheduleDefault= second="*/10", minute="*", hour="8-23", dayOfWeek="Mon-Fri",\n      dayOfMonth="*", month="*", year="*", info="MyTimer"
+errorTimerScheduleMissing=The schedule cannot be empty.
diff --git a/plugins/org.eclipse.jst.j2ee.ejb/templates/ejbtimer.javajet b/plugins/org.eclipse.jst.j2ee.ejb/templates/ejbtimer.javajet
new file mode 100644
index 0000000..83429b7
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ejb/templates/ejbtimer.javajet
@@ -0,0 +1,22 @@
+<%@ jet package="org.eclipse.jst.j2ee.ejb.internal.operations" 
+	imports="java.util.* org.eclipse.jst.j2ee.internal.common.operations.*" 
+	class="EjbTimerTemplate" 
+	skeleton="generator.skeleton"
+%>
+<% AddEjbTimerTemplateModel model = (AddEjbTimerTemplateModel) argument; %>
+<%@ include file="_flags.template" %>
+<%@ include file="_package.template" %>
+<%@ include file="_imports.template" %>
+@Stateless
+<%@ include file="_class.template" %>
+<%@ include file="_constructors.template" %>
+<%@ include file="_methods.template" %>
+	<%
+		String schedule = model.getProperty(AddEjbTimerDataModelProvider.SCHEDULE).trim();
+	%>
+	@SuppressWarnings("unused")
+	@Schedule(<%= schedule %>)
+    private void scheduledTimeout(final Timer t) {
+        System.out.println("@Schedule called at: " + new java.util.Date());
+    }
+}
\ No newline at end of file