ATG - How to start creating a Hello World component and module example? - atg

I'm new to ATG, and I've only been able to install ATG v10.2 successfully with JBoss.
However, since creating components and modules in ATG can be done in different ways, so I would like to know if there's any "Hello World" example for both module and component.
I have already searched in Google, but the different articles present in Internet don't mention point-wise in details, in a sequential manner.
So it will be great, if people can detail out the steps for a newbie, as I at least need to get started with one example, which I can later use as a base for other complex ones.
Thanks a lot to every one out there!
Note:-
I also know J2EE and MVC to some extent, where I can submit forms and save the user-input data to DB, without any significant issues.
I'm also going through the ATG Page Developer Guide at this moment.

There are so many concepts in ATG, that makes coming up with Hello World program little difficult. Do you mean to create one JSP page and deploy it like commerce reference store? Do you want to create a component just to see in Dyn/Admin? Do you want to create a hello world repository? Depending on what you want to do, the approach to take will be different.
To work with ATG, you don't have to know about saving values in database. If you approach ATG programming with J2EE & MVC experience, you may find it little difficult to cope with it unless you start with a fresh mind, because things are very different in ATG.
As #radimpe covered creating a hello world droplet, I will show how to create a simple component so that it can be viewed in Dyn/Admin.
Creating a HelloWorld component: That just appears in DynAdmin
Create an Eclipse project with following structure.
Following is the content of each of the file shown in the above screenshot
HelloWorldComponent.java
package com.buddha.components;
import atg.nucleus.GenericService;
import atg.nucleus.ServiceException;
public class HelloWorldComponent extends GenericService {
public String firstStr = "Dummy Value"; /* This value will be overwritten */
public String getFirstStr() {
return firstStr;
}
public void setFirstStr(String firstStr) {
this.firstStr = firstStr;
}
#Override
public void doStartService() throws ServiceException {
super.doStartService();
System.out.println("Hello ATG Component!");
}
#Override
public void doStopService() throws ServiceException {
super.doStopService();
System.out.println("Hello ATG Component! Stops now!");
}
}
Manifest.MF
Manifest-Version: 1.0
ATG-Required: DafEar.Admin
ATG-Config-Path: config/
ATG-Class-Path: ./bin/
HelloWorldComponent.properties
$class=com.buddha.components.HelloWorldComponent
firstStr=HelloWorld
Build the project and copy the project folder into ${DYNAMO_ROOT} and run the following command to generate an ear file of your project and deploy it in your jboss server.
runAssembler.bat -jboss HelloWorld.ear -m EXP_HelloATGComponentWorld
Navigate to Dyn/Admin and search for the component HelloWorldComponent and click on the component listed in the search results.
Click on it to go to the component page to see the property we have created and its value given in properties file.
You can observe the log as something like this
21:53:00,485 INFO [stdout] (http-/0.0.0.0:8080-1:ipaddr=127.0.0.1;path=/dyn/admin/nucleus//com/buddha/components/HelloWorldComponent;sessionid=gT4bmHj5WKs1Rf85GN0Z+9Qu) Hello ATG Component! This line is generated because of the sysout in our doStartService();
You can also give other methods that can be called through dyn/admin or interact with other components. Best of Luck.
Source: Creating a component in Oracle Commerce Platform

This is quite a broad topic and, in general, the Hello World example will only get you started with getting some text rendered on the screen. Most of your front-end interaction would happen with FormHandlers and Droplets of which the Droplet will get you the Hello World text on the screen. So lets start with that.
<%-- JSTL --%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%-- DSP --%>
<%-- This tag library represents the ATG tags --%>
<%# taglib prefix="dsp" uri="http://www.atg.com/taglibs/daf/dspjspTaglib1_0" %>
<%-- All, non-static includes will have a wrapping page tag --%>
<dsp:page>
<%-- A droplet is almost like a servlet, and here you include the name of the droplet you want to call --%>
<dsp:droplet name="/com/acme/droplet/HelloWorldDroplet">
<%-- An 'output parameter' matches the name of the 'service parameter' in your droplet. You can have multiple of these --%>
<dsp:oparam name="output">
<%-- The 'param' matches the name of the 'setParameter' in your droplet and can also be assigned to a jstl variable below --%>
Hello <dsp:valueof param="toWhom" />
</dsp:oparam>
</dsp:droplet>
</dsp:page>
Now create a 'component'. This is the property file that will map between the JSP page and the CLASS file (ie. you reference this in the droplet name)
File: /com/acme/droplet/HelloWorldDroplet.properties
$class=com.acme.droplet.HelloWorldDroplet
$scope=global
And now create your Java file: (/com/acme/droplet/HelloWorldDroplet.java)
public class HelloWorldDroplet extends DynamoServlet {
public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {
//This will allow you to pass a parameter to the droplet eg: hello.jsp?who=Peter
String who = pRequest.getParameter("who");
//Do a check on whether to display the default value or the one passed in
if (StringUtils.isEmpty(who)) {
//'toWhom' is the name of the param on the JSP page
pRequest.setParameter("toWhom", "World");
} else {
pRequest.setParameter("toWhom", who);
}
//'output' is the name of the 'oparam' on the JSP page.
pRequest.serviceParameter("output", pRequest, pResponse);
}
}
Hopefully that will be enough to get you started.

You can also have a look at below page.. it well explains the concept of What Actualy is a component and how can we use it..
http://learnoracleatg.blogspot.in/2014/10/art108-extending-out-of-box-components.html
You can also start right from the basics by pressing the "The Basics" button on the navigation bar.. it explains the concepts really well..

Check http://www.asknsay.com/creating-new-atg-project-in-eclipse.html for creating new application in atg from scratch using eclipse. It also covers how to deploy it in JBOSS 6.1.

Related

How to use a method with SafeHtml param instead of String in UiBinder (XML)?

We're migrating our application from GXT 3 to GXT 4 (and also from GWT 2.5 to 2.8.2) and one of the things that changed is that lot of components' body/text/heading/etc. now have two separate setters. One accepts String param and the other one accepts SafeHtml.
Here's an example:
public void setToolTip(SafeHtml html) {
...
}
public void setToolTip(String text) {
...
}
The difference in those is that the method accepting String does not render html elements. The other one, however, does, which is perfectly fine if one uses Java code to build UI.
Unfortunately, we do have a lot of our UI built using GWT's XML method and I would like it to stay this way.
The problem is that I cannot figure out how to show e.g. a tooltip with SafeHtml body. When I try to do that I get compilation errors.
This is what I put in my XML file:
...
<form:TextArea ui:field="testField" toolTip="{messages.testMesssage}" >
...
And this is the error:
[ERROR] java.lang.String required, but {testMess.test} returns com.google.gwt.safehtml.shared.SafeHtml: <form:TextArea toolTip='{messages.testMesssage}' ui:field='testField'> (:184)
Thanks!
You may want to look at the GXT examples for tooltips in UiBinder. In there, it shows using the ToolTipConfig instead of trying to set "tooltip" directly.
<ui:with type="com.sencha.gxt.widget.core.client.tips.ToolTipConfig"
field="toolTipConfig">
<ui:attributes title="Information" body="Prints the current document" />
</ui:with>
...
<form:TextArea ui:field="testField" toolTipConfig="{toolTipConfig}" />

How do I not include scripts and clientlibs in an experience fragment when exporting to Adobe Target?

I'm trying to build an experience fragment (XF) template in AEM 6.5. We have some custom clientlibs that I want to include when designers are authoring the experience fragment but I don't want to include when the experience fragment is injected via Adobe Target as the clientlibs will already be included on the base page template.
I want the clientlibs on the XF template so components render properly while designing. I've tried building a new page component based on /libs/cq/experience-fragments/components/xfpage and then checking the runmode for author or publish and using the result of that in a data-sly-test to conditionally include them. But I think because the Export to Target option happens on Author, it's including the scripts in the html output when it's exported to Target.
How do I conditionally include clientlibs during authoring of an XF, but not include them when the experience fragment is exported to target and added to a page from there?
There are couple of things you need to do in order to achieve this.
AEM offers the Link Rewriter Provider Interface. This is a ConsumerType interface that you can implement in your bundles, as a service.
It bypasses the modifications AEM performs on internal links of an HTML offer as rendered from an Experience Fragment. This interface allows you to customize the process of rewriting internal HTML links to align with your business needs.
To use the interface you first need to create a bundle containing a new service component that implements the Link Rewriter Provider interface.
This service will be used to plug into the Experience Fragment Export to Target rewriting in order to have access to the various links.
import com.adobe.cq.xf.ExperienceFragmentLinkRewriterProvider;
import com.adobe.cq.xf.ExperienceFragmentVariation;
import org.osgi.service.component.annotations.Service;
import org.osgi.service.component.annotations.Component;
#Component
#Service
public class GeneralLinkRewriter implements ExperienceFragmentLinkRewriterProvider {
#Override
public String rewriteLink(String link, String tag, String attribute) {
return null;
}
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return false;
}
#Override
public int getPriority() {
return 0;
}
}
shouldRewrite
You need to indicate to the system whether it needs to rewrite the links when a call is made for Export to Target on a certain Experience Fragment variation. You do this by implementing the method:
shouldRewrite(ExperienceFragmentVariation experienceFragment);
For example:
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return experienceFragment.getPath().equals("/content/experience-fragment/master");
}
This method receives, as a parameter, the Experience Fragment Variation that the Export to Target system is currently rewriting.
In the example above, we would like to rewrite:
links present in src
href attributes only
for a specific Experience Fragment:
/content/experience-fragment/
Any other Experience Fragments that pass through the Export to Target system are ignored and not affected by changes implemented in this Service.
rewriteLink
For the Experience Fragment variation impacted by the rewriting process, it will then proceed to let the service handle the link rewriting. Everytime a link is encountered in the internal HTML, the following method is invoked:
rewriteLink(String link, String tag, String attribute)
As input, the method receives the parameters:
link
The String representation of the link that is currently being processed. This is usually a relative URL pointing to the resource on the author instance.
tag
The name of the HTML element that is currently being processed.
attribute
The exact attribute name.
If, for example, the Export to Target system is currently processing this element, you can define CSSInclude as:
<link rel="stylesheet" href="/etc.clientlibs/foundation/clientlibs/main.css" type="text/css">
The call to the rewriteLink() method is done using these parameters:
rewriteLink(link="/etc.clientlibs/foundation/clientlibs/main.css", tag="link", attribute="href" )
When you create the service you can make decisions based on the given input, and then rewrite the link accordingly.

Given a Path get a reference to the Resource in Sightly

The component dialog has a pathfield widget where the authors can set a page path. In the Sightly component, I would like to look up that page resource and get (and display) properties from it.
The dialog...
<linkedPathLocation jcr:primaryType="cq:Widget"
fieldLabel="Linked Path"
name="./linkedPathLocation"
xtype="pathfield"
fieldDescription="Select a page. URL, Title, Description and Image are properties of the selected page"/>
The component code I would like to work (it's not).
<div class="row" data-sly-resource.page = "${properties.linkedPathLocation}">
<h1 >${page.title}</h1>
<p>${page.description}</p>
</div>
My question: Is there a way in Sightly to resolve and use some resource from a given path? If not, I could create a USE-API class and to do the following...
Page page = resourceResolver.resolve("/path/to/resource").adaptTo(Page.class);
I feel there should be a better answer which allows resources to be resolved directly from the Sightly, but the following USE-API solution works if not...
Java Use Class
public class PageHelper extends WCMUsePojo {
String pagePath = "";
#Override
public void activate() {
pagePath = get("path", String.class);
}
public Page getPage() {
return this.getPageManager().getPage(pagePath);
}
}
The component Sightly...
<div class="row" data-sly-use.linkedPage = "${'com.package.PageHelper' # path = properties.linkedPathLocation}">
<h1 >${linkedPage.page.title}</h1>
<p>${linkedPage.page.description}</p>
</div>
What you are trying to do, in essence, is render a Resource within the context of the rendering of another Resource. data-sly-resource seems the appropriate attribute to use, but instead of attempting to nest additional elements into the element containing the data-sly-resource you should define another Sightly .html file which dictates how the nested resource is to be rendered.
Let us say that your Resource is of type application/components/content/type. Within type.html you might have the following statement
<sly data-sly-resource="${properties.linkedPathLocation} # resourceType='application/components/content/type/subtype' />
You would then be able to define /apps/application/components/content/type/subtype/subtype.html containing the rendering to produce which would be invoked in the context of the Resource identified by your path.
The main purpose of Sightly templates is separation of responsibility (frontend & backend) so that we can have simple, clean and beautiful html markup which is designer friendly and easily readable.
For your case, writing a Class (Java/Javascript) to process dialog information, and supply it back to Sightly template is correct way. Read here for more details.

How does my frontend usergroup list get lost between Extbase action controller and Fluid template partial in TYPO3 6.2?

I'm using TYPO3 CMS 6.2.12 and Extension Builder 6.2.0 to model a Report class and build an extension to manage it.
One of the domain driven design requirements is that a report author be a logged-in front end user. A second requirement is that the author choose a single group from a list of their front end user groups while entering their report information.
Extension Builder did most of the work in producing code and files, so far. It built the Report model and all the action controllers and Fluid templates and partials. That's a huge leap forward. I did not have it build a model for front end users or their groups, opting instead to inject dependencies from existing classes. I am now trying to work on the user and usergroup requirements, mostly by adding code to the `newAction` controller and the Fluid partial for `FormFields`.
On my development server, I can enter new reports successfully. I bring up a web form for a new report; I can enter information and submit the new report; the newly created report appears in the list page and in the database; and I can show that single report in the web browser.
My problem now is that the frontend usergroup list does not appear in the web form for a new report.
I've been trying a variety of experiments over the last several days.
["A journey through the blog example"][blogexample] in the Extbase Fluid Book gave a good example to follow, and confidence that what I'm attempting to do should work. ["Alternative route: creating a new posting"][newposting] was especially useful as a guide, after reading the rest of the chapter.
TYPO3 Wiki's ["Dependency Injection" article][depinj] seems to say we need only #inject annotation, and although the article warns against t3lib_div::makeInstance, I found that a relocated version of that method became useful during the testing, below.
The Fluid debug instruction in the code below came from the TYPO3 Wiki's [Fluid page][fluid]. During testing, though, it seemed to give only TypoScript setting variables.
I found a number of Stack Overflow articles, including ["How to set the FrontendUserGroup in AllowViewHelper of VHS in a partial?"][so1] asked by Vertex, ["how to: use Tx_Extbase_Domain_Repository_FrontendUserRepository in typo3 v4.5"][so2] asked by The Newbie Qs, ["TYPO3 - Call another repository"][so3] asked by Jeppe Donslund, and ["Typo3 6.1 Extbase - select all fe users"][so4] asked by cili. This last article gave the $feUserRepository snippet I used in testing, below. The second-to-last article gave the warning, "After adding a Dependency Injection, you have to clear the cache!" It didn't say which cache, and that led to my drastic procedure of clearing everything I could think of for this test.
Today, I ran my most recent test with the code shown here, below. In the TYPO3 back end, I flushed frontend caches and flushed general caches. I went into the Install Tool's "Important actions" and clicked "Clear all cache". It was successful. I then went into the Extension Manager, where I deactivated and reactivated my extension. I then ran Debug in PhpStorm 8.0.3, which followed events. In my development website, I logged in to the front end. I navigated to the report listing page, and clicked "New Report". With break points set in `newAction()`, PhpStorm's watches told me they had an "error evaluating code" for both `$frontendUserRepository` and `$frontendUserGroupRepository`, with no further information that I knew how to find. (I'm new to PhpStorm.) However, `$feUserRepository` became an object of type `TYPO3\CMS\Extbase\Domain\Model\FrontendUser`, containing many items including an `identifierMap` array that contained arrays of `typo3\cms\extbase\domain\model\frontenduser` and `typo3\cms\extbase\domain\model\frontendusergroup` items. The frontenduser array contained a `TYPO3\CMS\Extbase\Domain\Model\FrontendUser` object that contained the correct user record. The frontendusergroup array contained 2 `TYPO3\CMS\Extbase\Domain\Model\FrontendUserGroup` objects that contained the correct user group records. In the next debug step, the `TYPO3\CMS\Extbase\Domain\Model\FrontendUser $user` object contained the same correct user record. After all this, though, the output HTML page for the new report's web form produced blanks for my author's username display and my author's usergroup select list. (The Extbase utility debugger showed only irrelevant TypoScript settings.)
This test leads me to believe that the Extbase `newAction` controller can find the frontend usergroups for `$feUserRepository`, but is having trouble with `$frontendUserRepository` and `$frontendUserGroupRepository`. However, indicated by the second empty break tag output line, below, even the `authortest` variable assigned to `$feUserRepository got lost, somehow, on the way to Fluid.
I'm trying for minimal impact on the rest of the package, and what I can find tells me this code below should be working. But it's not.
Can you tell what I missed?
(Please excuse my missing hyperlinks. Stack Overflow is telling me, "You need at least 10 reputation to post more than 2 links. This is my first question, so that obviously hasn't happened, yet.)
From myextension\Classes\Controller\ReportController.php:
/**
* reportRepository
*
* #var \MyVendor\Myextension\Domain\Repository\ReportRepository
* #inject
*/
protected $reportRepository = NULL;
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
* #inject
*/
protected $frontendUserRepository;
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserGroupRepository
* #inject
*/
protected $frontendUserGroupRepository;
/**
* action new
*
* #param \MyVendor\Myextension\Domain\Model\Report $newReport
* #ignorevalidation $newReport
* #return void
*/
public function newAction(\MyVendor\Myextension\Domain\Model\Report $newReport = NULL) {
$this->view->assign('newReport', $newReport);
$this->view->assign('author', $this->frontendUserRepository->findByUid($GLOBALS['TSFE']->fe_user->user['uid']));
$this->view->assign('groups', $this->frontendUserGroupRepository->findAll());
$feUserRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( 'TYPO3\\CMS\\Extbase\\Domain\\Repository\\FrontendUserRepository' );
$user = $feUserRepository->findByUid( 1 );
$this->view->assign('authortest', $user);
}
From myextension\Resources\Private\Templates\Report\New.html:
<f:form action="create" name="newReport" object="{newReport}">
<f:render partial="Report/FormFields" />
<f:form.submit value="Create new" />
</f:form>
From myextension\Resources\Private\Partials\Report\FormFields.html:
<f:debug title="All available variables">{_all}</f:debug>
{author.username}<br />
{authortest.username}<br />
<label for="authorGroupId"><f:translate key="tx_myextension_domain_model_report.author_group_id" /></label><br />
<f:form.select property="authorGroupId" options="{groups}" optionLabelField="title" optionValueField="uid" /><br />
From HTML output in the web form for a new report:
<br />
<br />
<label for="authorGroupId">Author Group Id</label><br />
<select name="tx_myextension_myextensionauthorplugin[newReport][authorGroupId]"><option value=""></option>
</select><br />
Your variables are not passed to the partial, so {groups} is not a variable inside your Partial.
You can specify the variables you want to use in the partial by giving the attribute arguments on your <f:render.partial> like in your case:
<f:render partial="Report/FormFields" arguments="{groups : groups}" />
Since TYPO3 4.6 you can also use arguments="{_all}" to pass all variables to the partial.
See also:
http://docs.typo3.org/flow/TYPO3FlowDocumentation/stable/TheDefinitiveGuide/PartV/FluidViewHelperReference.html#f-render
arguments (array, optional): Arguments to pass to the partial.

How to detect the browsers language in the EntryPoint SmartGWT

I'm developping a project with SmartGWT and I want to make it international,but how to know the browser's language in my EntryPoint (onModuleLoad) ?
I'm using Spring in the Server Side, and in my onModuleLoad I'm sending an RPC call to my Service which is gathering data from properties Files and respond with a Map contains all my keys value for internationalization, so while creating IU Widgets I'm using my Map like this lables.get("myLabel").
now that everytings is working fine, I want to detect the browser's language and use it for querying the right properties.
Sorry if my english is so bad
com.google.gwt.i18n.client.LocaleInfo#getCurrentLocale()
then I ended with a dirty solution, I created a javascript function as Lt_Shade told me,which put the navigator.language, then I retreive it in my EntryPoint thanks to the Document object, the probleme was when I run with IE or FireFox, the EntryPoint run before my HTML Page, so before my Javascript function and I dont find my navigator.language, so what I did is to create a JSNI function which call my javascript object within my EntryPoint (Calling Javascript function from java:gwt code) so I emphasize and insist the call then I'l sure that my navigator.language is loaded and I can retreive it.
in my HTML page
....
<script language="javascript">
function loadLocaleLanguage(){
document.getElementById("localeLanguage").setAttribute("value",(navigator.language).substring(0,2); // I don't need Country code
}
</script>
...
<input type="hidden" id="localeLanguage" value="" />
....
in my EntryPoint
public static native void getLocaleLanguage() /*-{
$wnd.loadLocaleLanguage();
}-*/;
public void onModuleLoad(){
// I call my javascript function to ensure that the input have my localeLanguage
getLocaleLanguage();
// now I'm retreiving it using DOM thanks to Document object
String localeLanguage = Document.get().getElementById("localeLanguage").getAttribute("value");
....
}
I'm sure that's not the best solution but at least it works
if someone can help me find how to acces the httpRequest within the EntryPoint (it containts the accept-language) or to directly acces the navigator.language in the EntryPoint, it'll be better.
thanks guys
I am not sure if this helps but there is a question like this which includes some java code for getting the language in a Java servlet.
Automatically selecting country and language for user in Java Servlet
You could also try add a JavaScript function into your EntryPoint something like
var userLang = (navigator.language) ? navigator.language : navigator.userLanguage;
alert ("The language is: " + userLang);