I'm using JDepend to analyze my architecture and create structural tests to verify dependency within a Layered architecture. The two relevant layers are com.domain and com.infrastructure. Domain concretely depends on the Infrastructure layer.
Why is the following test failing?
import java.io.IOException;
import jdepend.framework.DependencyConstraint;
import jdepend.framework.JDepend;
import jdepend.framework.JavaPackage;
import junit.framework.TestCase;
public class DependencyTest extends TestCase {
private JDepend jdepend;
#Override
public void setUp() throws IOException {
jdepend = new JDepend();
jdepend.addDirectory("build/classes/com");
}
public void testDomainDependsOnInfastructure_ShouldBeTrue() {
DependencyConstraint constraint = new DependencyConstraint();
JavaPackage domainPackage = constraint.addPackage("com.domain");
JavaPackage infastructurePackage = constraint.addPackage("com.infrastructure");
domainPackage.dependsUpon(infastructurePackage);
jdepend.analyze();
assertEquals("Domain doesn't depend on Infrastructure layer", true, jdepend.dependencyMatch(constraint));
}
}
jdepend.analyze() returns the relevant packages, so I do know it is finding my code. Any ideas?
Figured it out. JDepend's match function checks all packages, including libraries. I had to custom load it with just the packages I wanted. Here's the code that resolved my problem, if anyone ever runs into this problem.
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import jdepend.framework.DependencyConstraint;
import jdepend.framework.JDepend;
import jdepend.framework.JavaPackage;
import junit.framework.TestCase;
public class DependencyTest extends TestCase {
private JDepend jdepend;
#Override
public void setUp() throws IOException {
jdepend = new JDepend();
jdepend.addDirectory("build/classes/com");
}
public void testDomainDependsOnInfastructure_ShouldBeTrue() {
DependencyConstraint constraint = new DependencyConstraint();
JavaPackage distribution = constraint.addPackage("com.distribution");
JavaPackage domainPackage = constraint.addPackage("com.domain");
JavaPackage infastructurePackage = constraint.addPackage("com.infrastructure");
distribution.dependsUpon(domainPackage);
domainPackage.dependsUpon(infastructurePackage);
jdepend.analyze();
Collection<JavaPackage> actual = new ArrayList<JavaPackage>();
actual.add(domainPackage);
actual.add(distribution);
actual.add(infastructurePackage);
assertEquals("Domain doesn't depend on Infrastructure layer", true, constraint.match(actual));
}
}
Related
I am replacing PortletAdapter with GenericPortlet class in code. I followed this link - https://help.hcltechsw.com/digital-experience/9.5/dev-portlet/jsrmig.html. I am trying to initialize HATS-Host Access Transformation Services methods (see initializeHats() method) and it needs ServletConfig as a parameter. But I am not able to access the getServletConfig() method in the GenericPortlet class. I passed getPortletConfig() but got a null pointer exception. Below are my old code and new code. What is the replacement for the getServletConfig()?
Old code:
package abcpostavailablefreight;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlet.event.*;
import com.ibm.hats.runtime.connmgr.Runtime;
import com.ibm.hats.util.LicenseManager;
public class AbcPostAvailableFreightPortlet extends PortletAdapter implements ActionListener {
public void init(PortletConfig portletConfig) throws UnavailableException {
super.init(portletConfig);
}
public void initializeHats() {
initHATS = true;
//Initialize and activate the HATS runtime RAS functions,
// including tracing, logging, PII retrieval, locale.
com.ibm.hats.util.Ras.initializeRas(getServletConfig());
//Create the license manager
LicenseManager.getInstance();
//Initialize Host Publisher/connection management runtime
Runtime.initRuntime(getServletConfig());
}
}
New Code:
package abcpostavailablefreight;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.portlet.*;
import javax.portlet.UnavailableException;
import javax.servlet.*;
import javax.servlet.http.HttpSession;
public class AbcPostAvailableFreightPortlet extends GenericPortlet{
public void init(PortletConfig portletConfig) throws UnavailableException, PortletException {
super.init(portletConfig);
}
public void initializeHats(ActionRequest request) {
initHATS = true;
//Initialize and activate the HATS runtime RAS functions,
// including tracing, logging, PII retrieval, locale.
com.ibm.hats.util.Ras.initializeRas(getPortletConfig());
//Create the license manager
LicenseManager.getInstance();
//Initialize Host Publisher/connection management runtime
Runtime.initRuntime(getPortletConfig());
}
}
I develop a test for the mobile application using Cucumber+Junit+Appium. When I try to run a test using cucumber and JUnit runner I receive: io.cucumber.junit.UndefinedStepException: The step "I install the application" is undefined. You can implement it using the snippet(s) below:
I tried some of the solutions from the medium blog and stack question, but this doesn't help.
I have a project structure:
src
|-main
|--java
|---{project-name}
|----config
|----models
|----screens
|----services
|-test
|--java
|---{project-name}
|----helpers
|----stepDefinitions
|-----LoginStep.java
|-----BaseStep.java
|-----LoginStep.java
|----RunCucumber.java
|--resources
|---feature
|----Login.feature
RunCucumber.java
package com.mobile.automation.framework;
import com.google.inject.Guice;
import com.mobile.automation.framework.module.ServiceModules;
import com.mobile.automation.framework.service.AppiumServer;
import com.mobile.automation.framework.config.drivers.DriverFactory;
import com.mobile.automation.framework.module.ScreensModule;
import io.appium.java_client.AppiumDriver;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
strict = true,
monochrome = true,
glue = "src.test.java.com.mobile.automation.framework.stepDefinition",
features = "src/test/resources/feature",
plugin = {"pretty", "html:target/cucumber-report/cucumber.html",
"json:target/cucumber-report/cucumber.json",
"junit:target/cucumber-report/cucumber.xml"})
public class RunCucumber {
public static AppiumDriver driver;
#Before
public void setUpDriver() {
init();
new AppiumServer().startServer();
driver = new DriverFactory().getDriver();
}
#After
public void tearDownDriver() {
if (driver != null) {
driver.quit();
new AppiumServer().stopServer();
}
}
private void init() {
Guice.createInjector(
new ScreensModule(driver),
new ServiceModules(driver)
).injectMembers(this);
}
}
Login.feature
Feature: Sign In feature
Background:
Given I install application
And I enable all network activity
Then I am on Sign Page
Scenario: Sign In scenario
Given I am go to the Login Page
And I fill valid user data using "Config"
And I click sign in button
Then I am login in the application
LoginStep.java
package com.mobile.automation.framework.stepDefinition;
import javax.inject.Inject;
import com.mobile.automation.framework.config.ProjectConfig;
import com.mobile.automation.framework.models.User;
import com.mobile.automation.framework.screens.DashboardScreen;
import com.mobile.automation.framework.screens.SignInScreen;
import io.cucumber.java.ParameterType;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
/**
* #author Tomash Gombosh
*/
public class LoginStep {
#Inject
private SignInScreen signInScreen;
#Inject
private DashboardScreen dashboardScreen;
#Given("^I am go to the Login Page$")
public void iAmGoToTheLoginPage() {
dashboardScreen.tapLogin();
}
#And("I fill valid user data using {string} {string}")
public void iFillValidUserDataUsing(String userName, String password) {
signInScreen.fillLogin(userName, password);
}
#And("I fill valid user data using {string}")
#ParameterType("Config")
public void iFillValidUserDataUsing() {
signInScreen.fillLogin(new User(data -> {
data.setEmail(new ProjectConfig().getBaseUser());
data.setPassword(new ProjectConfig().getBaseUserPassword());
}));
}
#And("I click sign in button")
public void iClickSignInButton() {
signInScreen.clickLogin();
}
#Then("I am login in the application")
public void iAmLoginInTheApplication() {
assertThat(signInScreen.isDisplayed()).isEqualTo(true);
}
}
Some of the steps on the Login class is missing, but that is because I want to put all the code to the question.
I expected to run that feature, but actually that is not work.
Typically src.test.java is not part of the package name. Try using:
glue = "com.mobile.automation.framework.stepDefinition",
And because Cucumber will search the runners package for glue by default can also remove the glue entirely.
New here myself working on Junit Runner, I agree with #M.P.Korstanje with classpath. Although I just had to change glue to refer the stepDefs with classpath too - wasn't getting recognized before.
So basically this is what I did to catch the necessary files to be triggered
feature = { "classpath:path-from-repo-root.feature" },
glue = { "classpath:reference-to-stepDef-folder" }
Bear in mind: for glue - I used to the reference to the folder containing the stepDefs and not the stepDef file itself. Hope this helps someone. Thanks
I have been trying to make LeanFT html reports work with my Selenium/Junit framework, however so far without any joy.
I have searched the topic multiple times on different forums incl. HP official materials and tried all setup methods that I could find.
An XML runresults file is still generated when using a custom Selenium/LeanFT framework.
I create a LeanFT Testing Project project using JUnit as my framework and Selenium as SDK. I also add relevant Selenium jars.
LeanFT version is 14.0.2816.0.
I am conscious of this issue: https://community.softwaregrp.com/t5/UFT-Practitioners-Forum/HTML-report-not-generated-in-custom-framework-using-LeanFT/td-p/1614027 .
I would be grateful, if someone could explain where I am making a mistake here or if the software version is the problem here. Any help is very much appreciated.
The actual setup contains more abstractions, is generally more complex and runs as a jar file, but I have simplified the code for the purpose of this topic as the outcome of both setups is the same - a runresults.xml and no html:
Test Class:
import com.hp.lft.report.CaptureLevel;
import com.hp.lft.report.ModifiableReportConfiguration;
import com.hp.lft.report.Reporter;
import com.hp.lft.sdk.ModifiableSDKConfiguration;
import com.hp.lft.sdk.SDK;
import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserDescription;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;
import core.Selenium;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.*;
import java.io.File;
import java.net.URI;
public class SeleniumTest extends Selenium {
WebDriver driver;
Browser browser;
public SeleniumTest() {
//Change this constructor to private if you supply your own public constructor
}
#BeforeClass
public static void setUpBeforeClass() throws Exception {
instance = new SeleniumTest();
globalSetup(SeleniumTest.class);
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
globalTearDown();
}
#Before
public void setUp() throws Exception {
ModifiableSDKConfiguration sdkConfig = new ModifiableSDKConfiguration();
sdkConfig.setServerAddress(new URI("ws://localhost:5095"));
SDK.init(sdkConfig);
ModifiableReportConfiguration reportConfig = new ModifiableReportConfiguration();
reportConfig.setOverrideExisting(true);
reportConfig.setTargetDirectory("C:\\Users\\user\\IdeaProjects\\LeanFT_Selenium\\RunResults");
reportConfig.setReportFolder("LastRun");
reportConfig.setTitle("Summary");
reportConfig.setDescription("Description");
reportConfig.setSnapshotsLevel(CaptureLevel.All);
Reporter.init(reportConfig);
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File
("C:\\Program Files (x86)\\HP\\Unified Functional Testing\\Installations\\Chrome\\Agent.crx"));
System.setProperty("webdriver.chrome.driver",
"C:\\HP_Reporting\\Webdriver\\chromedriver.exe");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(options);
browser = BrowserFactory.attach(new BrowserDescription.Builder()
.type(BrowserType.CHROME).build());
}
#After
public void tearDown() throws Exception {
driver.quit();
browser = null;
Reporter.generateReport();
SDK.cleanup();
}
#Test
public void test() throws Exception {
driver.get("https://www.google.co.uk/");
}
}
Selenium Class:
import com.hp.lft.report.Status;
import com.hp.lft.unittesting.UnitTestBase;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
public class Selenium extends UnitTestBase{
protected static Selenium instance;
public static void globalSetup(Class<? extends Selenium> testClass) throws Exception {
if (instance == null)
instance = testClass.newInstance();
instance.classSetup();
}
#Before
public void beforeTest() throws Exception {
testSetup();
}
#After
public void afterTest() throws Exception {
testTearDown();
}
public static void globalTearDown() throws Exception {
instance.classTearDown();
getReporter().generateReport();
}
#ClassRule
public static TestWatcher classWatcher = new TestWatcher() {
#Override
protected void starting(org.junit.runner.Description description) {
className = description.getClassName();
}
};
#Rule
public TestWatcher watcher = new TestWatcher() {
#Override
protected void starting(org.junit.runner.Description description) {
testName = description.getMethodName();
}
#Override
protected void failed(Throwable e, org.junit.runner.Description description) {
setStatus(Status.Failed);
}
#Override
protected void succeeded(org.junit.runner.Description description) {
setStatus(Status.Passed);
}
};
#Override
protected String getTestName() {
return testName;
}
#Override
protected String getClassName() {
return className;
}
protected static String className;
protected String testName;
}
Libraries
TL;DR
The report is only generated in 14.00 by extending UnitTestBase. To have the report generated with a custom automation framework, you must upgrade to at least LeanFT 14.01 (latest one at the time of writting is 14.02 though).
Oh, and just for clarification: this issue has nothing to do with Selenium. You'd have the same behavior in C# LeanFT SDK using NUnit 3, for example.
Details
What is a custom automation framework in this context?
When I say custom automation framework I mean any framework that does the SDK and Reporter initialization and cleanup itself.
LeanFT does all the magic through its engine. To tell a custom framework to connect to the engine, you need perform the following steps:
at the beginning of a test suite:
SDK.init();
Reporter.init(); // This is not for the engine, but for the HTML report generation
at the end of a test suite
Reporter.generateReport();
SDK.cleanup();
When you are using the builtin templates, you'll notice that a UnitTestClassBase class is automatically created, that extends from UnitTestBase and that your LeanFtTest class extends from this UnitTestClassBase.
By doing so you are initializing the SDK and the Reporter in a very specific way, which is the reason why with this initialization the HTML report is generated. If you were to reproduce this specific way in your custom framework, you'll also have the HTML report generated. If you are curious, you can check the contents of the UnitTestBase.class file to see what it does.
You are extending from UnitTestBase. Why is it not working?
As mentioned in my comments, you are actually doing the SDK and Reporter initialization twice, once by extending the UnitTestBase (which, as I described above, does that initialization already) and the second time in your setUp method.
Since you are using LeanFT 14.00, you should let the UnitTestBase do the initialization, cleanup and report generation. This means that your Test Class file should be changed to no longer include the init of the SDK and Reporter, as follows:
import com.hp.lft.report.CaptureLevel;
import com.hp.lft.report.ModifiableReportConfiguration;
import com.hp.lft.report.Reporter;
import com.hp.lft.sdk.ModifiableSDKConfiguration;
import com.hp.lft.sdk.SDK;
import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserDescription;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;
import core.Selenium;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.*;
import java.io.File;
import java.net.URI;
public class SeleniumTest extends Selenium {
WebDriver driver;
Browser browser;
public SeleniumTest() {
//Change this constructor to private if you supply your own public constructor
}
#BeforeClass
public static void setUpBeforeClass() throws Exception {
instance = new SeleniumTest();
globalSetup(SeleniumTest.class);
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
globalTearDown();
}
#Before
public void setUp() throws Exception {
/*
This will not work in LeanFT 14.00, so we are commenting it out
ModifiableSDKConfiguration sdkConfig = new ModifiableSDKConfiguration();
sdkConfig.setServerAddress(new URI("ws://localhost:5095"));
SDK.init(sdkConfig);
ModifiableReportConfiguration reportConfig = new ModifiableReportConfiguration();
reportConfig.setOverrideExisting(true);
reportConfig.setTargetDirectory("C:\\Users\\user\\IdeaProjects\\LeanFT_Selenium\\RunResults");
reportConfig.setReportFolder("LastRun");
reportConfig.setTitle("Summary");
reportConfig.setDescription("Description");
reportConfig.setSnapshotsLevel(CaptureLevel.All);
Reporter.init(reportConfig);
*/
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File
("C:\\Program Files (x86)\\HP\\Unified Functional Testing\\Installations\\Chrome\\Agent.crx"));
System.setProperty("webdriver.chrome.driver",
"C:\\HP_Reporting\\Webdriver\\chromedriver.exe");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(options);
browser = BrowserFactory.attach(new BrowserDescription.Builder()
.type(BrowserType.CHROME).build());
}
#After
public void tearDown() throws Exception {
driver.quit();
browser = null;
//Reporter.generateReport();
//SDK.cleanup();
}
#Test
public void test() throws Exception {
driver.get("https://www.google.co.uk/");
}
}
But I need to configure the SDK and the Report. How can I achieve that in LeanFT 14.00?
The SDK and the Reporter can be configured in two ways:
At initialization, as you attempted to do through the ModifiableSDKConfiguration and ModifiableReportConfiguration
or
In the test settings file (resources/leanft.properties). You can see plenty details in the official help.
You can manipulate some report settings at runtime as well, through the Reporter API:
Set the report level: Reporter.setReportLevel(ReportLevel.All);
Set the snapshot capture level Reporter.setSnapshotCaptureLevel(CaptureLevel.All);
Even if you initialized the SDK and the Reporter through the base class, you can still add custom report events in the report (these work: Reporter.reportEvent();, Reporter.startReportingContext();, Reporter.startTest();, etc.)
I have an abstract class (database mapping) implementing an interface where default implementations are injected at runtime (this is part of another library and cannot be changed).
I want to override one of the default implementation via a proxy (as that seems like the way to override this).
public abstract class Table1 implements Storable<Table1>
{
#Sequence("ID_SEQUENCE")
#Alias("ID")
public abstract String getID();
public abstract void setID(String ID);
#Alias("NAME")
public abstract String getAvailabilityZone();
public abstract void setAvailabilityZone(String value);
}
public interface Storable<S extends Storable<S>> {
//a bunch of method definition.
boolean tryLoad() throws Exception;
}
Let's say I want to override tryLoad() method to do my own things instead of what the generated code provides. Given the nature of the library, it is not something I can achieve by simple #Override.
The simple way this is currently used is as following:
public void method() {
Table1 t = Repository.storageFor(Table1.class).prepare();
t.setName( "temp" );
if (!t.tryLoad())
t.tryInsert();
}
I want to proxy tryLoad() without making changes in all the methods across the whole codebase - that would be to get proxied instance instead of actual one and perform the operation on that.
Is there any recommended way to achieve this?
Thanks!
I woke up last night and felt bored, so despite your lack of feedback I created a little Carbonado showcase project and shared it on GitHub. I made three commits:
Initial commit with Maven project already prepared for AspectJ and a JUnit test for me to find out how Carbonado actually works, because I had never used it before.
Add failing unit test for behaviour of tryLoad() expected to be provided by aspect.
Add aspect to make unit test pass. Aspect hooks into tryLoad() and auto-creates non-existent record. I do not know if I guessed right what you actually wanted to achieve, but if it was a different thing, just change the aspect implementation.
Sample code
Carbonado storable:
package de.scrum_master.app;
import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
#PrimaryKey("ID")
public interface StoredMessage extends Storable<StoredMessage> {
long getID();
void setID(long id);
#Nullable String getMessage();
void setMessage(String message);
}
Aspect:
package de.scrum_master.aspect;
import com.amazon.carbonado.Storable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class CarbonadoAspect {
#Around("call(boolean tryLoad()) && target(storable)")
public boolean tryInsertIfNotFound(ProceedingJoinPoint thisJoinPoint, Storable storable) throws Throwable {
System.out.println(thisJoinPoint);
if ((boolean) thisJoinPoint.proceed())
return true;
System.out.println("Not found: " + storable + " -> inserting");
return storable.tryInsert();
}
}
JUnit test:
package de.scrum_master.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.repo.map.MapRepositoryBuilder;
import de.scrum_master.app.StoredMessage;
public class CarbonadoTest {
private Repository repo;
private Storage<StoredMessage> storage;
StoredMessage message;
#Before
public void setUp() throws Exception {
repo = MapRepositoryBuilder.newRepository();
storage = repo.storageFor(StoredMessage.class);
message = storage.prepare();
}
#After
public void tearDown() throws Exception {
repo.close();
repo = null;
storage = null;
message = null;
}
// (...)
#Test
public void aspectCreatesNonExistentRecord() throws SupportException, RepositoryException {
message.setID(1);
// Without the aspect this would be false
assertTrue(message.tryLoad());
assertEquals(message.getID(), 1);
assertEquals(message.getMessage(), null);
}
}
Enjoy!
I have downloaded the source code of Google App Engine and I would like to change the behavior of some methods (for example, DatastoreService.put(Entity e)) used in this example:
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class LocalDatastoreTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
// run this test twice to prove we're not leaking any state across tests
private void doTest() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
assertEquals(0, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
ds.put(new Entity("yam"));
ds.put(new Entity("yam"));
assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
}
#Test
public void testInsert1() {
doTest();
}
#Test
public void testInsert2() {
doTest();
}
}
The problem is that I do not see that the build.xml file provided with the source code makes any compilation of the source .java files. For example, when I add some garbage to one of the source files and try to build the SDK using ant dist it returns BUILD SUCCESSFUL rather than a compile time error.
Any ideas where can I find the source file of the put(Entity e) method? and how can I compile the source code?
You cannot make any changes to App Engine SDK. SDK exposes methods that are directly related to and dependent upon the internal operations of the App Engine and its Datastore. You are not supposed to compile the SDK separately from your source code.