Java EE Development using Rational Application Developer 7.5.5 and Maven Introduction

Java EE Development using Rational Application Developer 7.5.5 and Maven Introduction
Java EE Development using Rational Application
Developer 7.5.5 and Maven
by Chuck Bridgham, IBM
Introduction
IBM® Rational® Application Developer for WebSphere® 7.5 delivers a wide range of
integrated productivity enhancing tools for building Java™ EE, Web service, Portal, and
SOA solutions. Whether you are developing applications using the new EJB 3 or JPA
annotation tools, or reviewing existing applications using static code analysis, Rational
Application Developer is an IDE that integrates tools for designing, developing, testing,
and deploying your applications, effortlessly transitioning developers through the
software lifecycle.
The Apache Maven project has been around for a while, and many users have adopted the
build system’s practices and procedures, but are unsure how to integrate with a powerful
IDE such as Rational Application Developer.
This article is going to explore the basics of the Maven projects, and how they interact
with their Rational Application Developer equivalents. We’ll explore some best practices
building a Java EE 5 application targeting WebSphere Application Server 7.0. We’ll also
cover how nested projects can be used in Rational Application Developer, and what to
watch out for using a team SCM system. We’ll briefly cover some open source projects
aimed at automating many of the steps needed to integrate build environments within an
Eclipse™-based IDE such as Rational Application Developer. Finally, we’ll show a
Maven build in action using the Rational Team Concert build engine, integrated into the
Rational Application Developer 7.5 environment.
The Maven story
Whether you’re thinking about using Maven for the first time, or have been a long time
user, the benefits of the open build framework become quickly apparent. The following
is a very brief overview of Maven; more details are available on the Apache Maven home
page. (http://maven.apache.org/)
Maven assists developers and build coordinators to unify the wide range of build
requirements and standards into one system that is flexible enough for customization
while providing a common API that can be learned once and deployed company wide.
Maven has been available since 2001, and began with the desire to remove some of the
drudgery and duplication around creating ant scripts by specifying standards on simple
project types.
Page 1 of 30
With the addition of Maven plugins, standard build capabilities (goals) can be customized
and expanded. Maven archetypes are used as project templates, making it easy to enable
standards within your organization. The Maven repository not only provides a database
of sharable resources, but also shareable tasks, templates, and scripts.
What additional capabilities does Maven provide over ant?
• Predefined build conventions(or standards)
• Heavy use of defaulting
• Default tasks
• Default project structures
• Smart structured repository system
• Tools for continuous integration
Each Maven project provides a project object model (POM) file that captures
dependencies plus project properties, All of the default values can be overridden, which
adds to the size of the default POM.xml file.
Rational Application Developer can interact with Maven project structures by
understanding the project design and restrictions. The two tools can co-exist peacefully
with just a few rules and best practices.
Example 1: Rational Application Developer integration
for Maven projects
Part 1: Maven Sample Projects Explained
For this example, we will take an existing Java EE 5 application in Maven consisting of
several modules set up in a typical Maven structure, using a root project that contains an
EAR, EJB, utility, and servlet folders. We will demonstrate how to integrate these
projects into Rational Application Developer by creating projects around these existing
folders. This example will show how easy it is to compile, package, and install Maven
projects. This example does not demonstrate server test integration, because this is one of
Rational Application Developer’s strengths, which allows you to easily deploy and debug
Java EE applications to different server environments without the extra steps of
packaging and install. This example also does not integrate with any external plugins
such as m2eclipse that assist in the project classpath management based on the Maven
POM. By default, Rational Application Developer classpath management continues to
rely on static project MANIFEST files that convey the runtime availability of dependent
modules. Changing the POM.XML file will require also changing Rational Application
Developer’s dependency management located under each project’s J2EE Jar
Dependencies property sheet.
Page 2 of 30
WebSphere Application Server provides ant tasks for deployment and server
operations . See the following information center topic:
(http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.we
bsphere.base.doc/info/aes/ae/tovr_ant.html)
These tasks can be integrated using the maven-antrun-plugin
.(http://maven.apache.org/plugins/maven-antrun-plugin/)
The Maven project folder layout is standard, and is used to easily inherit properties and
behaviors from parent projects, keeping the leaf module pom.xml very clean.
Figure 1: Maven project layout
This Java EE 5 application has optional deployment descriptors in both the EJB and EAR
projects. This application will be targeting the WebSphere Application Server 7.0
runtime, which will provide the Java and Java EE runtime JAR files for compilation.
WebSphere Application Server ships a number of thin client JAR files for standalone
compilation, and are appropriate for installing into a MAVEN repository. More
information on the WebSphere Application Server 7 client JAR files is located here:
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websph
ere.base.doc/info/aes/ae/tcli_developthin.html
Page 3 of 30
Earlier versions of WebSphere Application Server also provide similar JAR files, and
should always be used to reflect the intended target environment. Here is an example of
installing a couple of these provided JAR files into your local Maven repository using the
WebSphere Application Server release level to specify the MAVEN artifact version.
mvn install:install-file Dfile=D:\IBM\SDP\runtimes\base_v7\runtimes\com.ibm.ws.ejb.thinclient_7.0.0.jar DgroupId=websphere -DartifactId=com.ibm.ws.ejb.thinclient -Dversion=7.0.0 Dpackaging=jar
mvn install:install-file Dfile=D:\IBM\SDP\runtimes\base_v7\runtimes\com.ibm.ws.jpa.thinclient_7.0.0.jar DgroupId=websphere -DartifactId=com.ibm.ws.jpa.thinclient -Dversion=7.0.0 Dpackaging=jar
Part 2: Preparing Maven Projects
Our two examples use most of the Maven project packaging and plugin defaults, but
several key properties are set to help integrate into the Rational Application Developer
workspace environment, and also integrate with the m2e plugins
Looking at the existing EJB project pom.xml file, you will notice the dependency to the
data project containing JPA entity classes, the EJB client JAR file, and the WebSphere
Application Server client JAR file. Some plugin properties are also set, such as the EJB
level to 3.0 to allow for an optional deployment descriptor, and specifying the existing
MANIFEST file location to use during maven packaging.
This allows Rational Application Developer to use a predefined MANIFEST file for its
development time classpath setup, rather than generating at publish time. This is an
important difference with m2eclipse sample shown later, where the MANIFEST is
generated based on the POM file contents.
Page 4 of 30
Listing 1: EJB pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>root.SampleProject</groupId>
<artifactId>MyCompanyEJB</artifactId>
<packaging>ejb</packaging>
<version>1.0</version>
<name>enterprise java beans</name>
<parent>
<groupId>root</groupId>
<artifactId>SampleProject</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>root.SampleProject.Utilities</groupId>
<artifactId>DataProject</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>root.SampleProject.Utilities</groupId>
<artifactId>MyCompanyEJBClient</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<!-- provided by the container -->
<groupId>websphere</groupId>
<artifactId>com.ibm.ws.ejb.thinclient</artifactId>
<version>7.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/java/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Next, in the EAR project pom file, include the dependent projects, which are used to
generate an application.xml. In our example for Java EE 5, we designated this file to be
omitted, and we added this option and EAR plugin version because this is a very new
feature, not available in versions prior to v2.3.2. If this was an EAR with an existing
application.xml file, you must set the applicationXML parameter of the EAR plugin.
Page 5 of 30
More EAR plugin info is available here: http://maven.apache.org/plugins/maven-earplugin/ear-mojo.html#applicationXml
Listing 2: Ear pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>root.SampleProject</groupId>
<artifactId>MyCompanyEJBEar</artifactId>
<packaging>ear</packaging>
<version>1.0</version>
<name>MyCompanyEJBEar</name>
<parent>
<groupId>root</groupId>
<artifactId>SampleProject</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>root.SampleProject</groupId>
<artifactId>MyCompanyEJB</artifactId>
<type>ejb</type>
</dependency>
<dependency>
<groupId>root.SampleProject.Utilities</groupId>
<artifactId>MyCompanyEJBClient</artifactId>
<version>1.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>root.SampleProject.Utilities</groupId>
<artifactId>DataProject</artifactId>
<version>1.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>root.SampleProject.servlets</groupId>
<artifactId>MyCompanyWeb</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<version>5</version>
<generateApplicationXml>false</generateApplicationXml>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.ear.final.name>MyCompanyEJBEAR.ear</maven.ear.final.name>
</properties>
</project>
Page 6 of 30
The rest of the utility projects are very straight forward, and use an inherited property to
always generate the MANIFEST using the existing file in place.
Listing 3: Utility pom.xml
<build>
…
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/java/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
The servlet's pom file also specifies generating the MANIFEST, and leaving out the
dependent libraries from the WEB-INF/lib directory. This must be specified through the
WAR plugin, with the latest version available.
Listing 4: Servlet pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<archive>
<manifestFile>src/main/java/META-INF/MANIFEST.MF</manifestFile>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
The parent SampleProject pom.xml is used for global configuration, for example
specifying JRE libraries and compiler levels.
Page 7 of 30
Listing 5: Parent pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.6</target>
<source>1.6</source>
</configuration>
</plugin>
</plugins>
</build>
This example also has one third party JAR file that is included in the EAR, to
demonstrate how applications can refer to these libraries. Run a one time install
command to include the third party JAR file in the Maven repository
mvn install:install-file Dfile=D:\MAVEN\RAD_PROJECTS\SampleProject\MyCompanyEJBEAR\src\main\application\MyCompa
nyUtilities.jar -DgroupId=root.SampleProject.Utilities -DartifactId=MyCompanyUtilities
-Dversion=1.0 -Dpackaging=jar
I have included a zip archive of the sample Maven projects prior to Rational Application
Developer integration.
After unzipping, try a couple of maven commands to ensure your environment is set up.
For instance: mvn install
If all went well, you should see similar output toward the end of the console.
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
[INFO]
-----------------------------------------------------------------------Reactor Summary:
-----------------------------------------------------------------------SampleProject ......................................... SUCCESS [7.219s]
Utility projects ...................................... SUCCESS [0.344s]
logging ............................................... SUCCESS [4.312s]
logging ............................................... SUCCESS [0.250s]
servlets .............................................. SUCCESS [0.016s]
MyCompanyWeb .......................................... SUCCESS [2.281s]
enterprise java beans ................................. SUCCESS [0.594s]
MyCompanyEJBEar ....................................... SUCCESS [0.922s]
----------------------------------------------------------------------------------------------------------------------------------------------BUILD SUCCESSFUL
-----------------------------------------------------------------------Total time: 16 seconds
Finished at: Sun Aug 09 14:21:29 EDT 2009
Final Memory: 19M/33M
------------------------------------------------------------------------
Page 8 of 30
Part 3: Understanding Rational Application Developer project
metadata
Before proceeding with project creation in Rational Application Developer, let’s identify
the metadata stored by Rational Application Developer that will help you gain an
understanding of the relationship with Maven metadata, and will prevent build and
synchronization issues between the two.
Simple Java projects in Rational Application Developer are based on the core (JDT)
Eclipse project:
File/Folder
Description
.project
Simple xml file listing natures and builders
installed on project.
.classpath
JDT xml file listing Java source and target
folders, JAR and class dependencies in
forms of containers and single entries
settings/.org.eclipse.jdt.core.prefs
compiler level, and other Java properties
Rational Application Developer Java EE projects add more complex metadata to your
project:
Page 9 of 30
File/Folder
Description
.settings/org.eclipse.wst.common.project.facet.core.xml XML file that captures more
.settings/org.eclipse.wst.common.component
MANIFEST.MF file
details regarding the
capabilities of the project, and
the target server runtime
environment
XML file that contains
resource mapping and
dependent library references
defining the “deployed”
module
In Rational Application
Developer, this file is
maintained at development
time, and is also used to
determine project
dependencies. This is different
than Maven, where this file is
generated at packaging time,
based on the pom.xml.
Part 4: Preparing for Rational Application Developer project
creation
You may notice that I have not included junit tests in the Maven project folders, although
this is perfectly legal. One issue that should be considered is the fact that Rational
Application Developer Java projects only support a single classpath. Mixing runtime and
test artifacts within the same project may produce undesirable results. Managing the
deployable contents of the module by manually editing the
.settings/org.eclipse.wst.common.component file can be messy. Therefore, it is
recommended to create separate test projects to hold junit tests, depending on your
runtime artifacts.
Rational Application Developer has several workspace project preferences that can be set
to mimic a Maven structure, and can be shared across your organization. Under the menu
Window> Preferences, select the Java EE > Project preference page. Use the
following MAVEN defaults:
Page 10 of 30
Figure 2: Java EE Project preferences
Page 11 of 30
Dependency synchronization
This example works because both Rational Application Developer and Maven are created
with parallel steps, carefully creating entries in each respective dependency mechanisms.
Maven uses pom.xml, and Rational Application Developer uses a combination of
MANIFEST.MF, and component metadata driven by the project properties defined in
Java EE Module Dependencies. Any changes to a project dependency must be
maintained in both mechanisms in this scheme.
Part 5: Creating Rational Application Developer Projects
As mentioned previously, Rational Application Developer Java projects only support a
single classpath, and a project should be created for each deployable unit to properly
emulate the runtime environment. When creating projects in Rational Application
Developer that overlay existing file structures, it is important to start from the parent
projects down. We will start with our root project, creating a simple non-Java project that
captures this Maven project. Be careful to clear the Use default location check box, and
use the same folder location under the Maven directories:
Figure 3: Simple Project creation
Page 12 of 30
Next create the two container projects servlets and Utilities using the same project
wizard, but carefully selecting the correct subfolder:
Figure 4: Servlet project creation
Page 13 of 30
Figure 5: Utility project creation
Page 14 of 30
Next we will create the EJB project MyCompanyEJB, selecting the correct folder
location, and also clearing the Add project to an EAR check box. Select module version
3.0, and always select the Target Runtime WebSphere Application Server v7.0 for our
example projects.
Figure 6: EJB project creation
Page 15 of 30
Next we’ll create the EAR project: MyCompanyEJBEAR, choosing the correct
location:
Figure 7: Ear project creation
Page 16 of 30
Next we’ll create the JPA project DataProject, carefully specifying the correct folder
location, from the New > Project > Java EE > JPA Project wizard, also clearing the
“Add project to an EAR” checkbox and unselecting “Create orm.xml”
Figure 8: JPA project creation
Page 17 of 30
Figure 9: JPA Facet Settings
Page 18 of 30
The next step is the EJB client project MyCompanyEJBClient. Carefully specify the
correct folder location, from the New > Project > Java EE > Utility wizard, also
clearing the Add project to an EAR check box.
Figure 10: EJB Client project creation
.
Page 19 of 30
The last project to be created is the Web project MyCompanyWeb. Select the menu
New > Project > Web > Dynamic Web Project , carefully specifying the correct folder
location, also clearing the Add project to an EAR checkbox. Click Next. Clear the
Generate Deployment Descriptor check box and then click Finish.
Figure 11: Web project creation
Page 20 of 30
Next we’ll add the projects to the EAR project by right-clicking the project and selecting
the Properties > Java EE Module Dependencies, and checking each project listed (4).
Figure 12: Configuring Ear
Page 21 of 30
The last
step is to add the JPA DataSource configuration to the WebSphere Application
Server configuration file. This is done by right-clicking the DataProject and selecting
JPA Tools > Configure Project For JDBC Deployment.
In the Enterprise Explorer view, select the DepartmentSalarySearch servlet. Rightclick and select Run as > Run on Server.
Figure 13: Test the application
Page 22 of 30
Figure 14: Result page
You’re done!
Page 23 of 30
Maven Eclipse Plugins
Choices exist now for several open source projects that assist with integrating Maven
metadata (POM) and goals with the Rational Application Developer infrastructure.
•
Apache Maven Eclipse plugin (one time creation of Eclipse project metadata
based on the project POM) http://maven.apache.org/plugins/maven-eclipseplugin/
•
M2Eclipse http://m2eclipse.sonatype.org/index.html (Eclipse incubator)
•
Integration for Apache Maven (IAM) http://www.eclipse.org/iam/ – (Eclipse
incubator)
Of these choices, the m2eclipse project is the most mature, and is gaining popularity
among developers. The project currently has a 0.10.0 release, and is compatible with the
Rational Application Developer Eclipse base under v7.5.5.x. These plugins offer a wide
variety of tools and integration points including:
• custom builders that are based on the Maven build
• Java “containers” that populate the classpath based on the POM library
dependency resolution,
• POM editors that aid in creation/editing and validation of these files
• creation wizards helping create new projects based on archetypes
• Maven command menu actions.
These options are not supported officially by IBM, but have active newsgroups and
mailing lists responsive to questions and issues that may arise.
M2 Update site:
Stable releases - http://m2eclipse.sonatype.org/sites/m2e
Page 24 of 30
Figure 15: m2eclipse update sites
Open Help > Software Updates and click the Available Software tab. Add the M2
update site noted above. In addition – before installing, make sure you also have the
GEF update site (http://download.eclipse.org/tools/gef/updates/releases/) and select under
GEF SDK 3.4.2(compatible with Rational Application Developer 7.5.5) the Zest
Visualization Toolkit.
The m2eclipse integration can further enhance the “overlay” sample in Rational
Application Developer by recognizing the Maven project’s POM file, and contributing
directly to the project’s classpath. There will be duplication on the classpath because
Rational Application Developer calculates the classpath based on the runtime structure
(MANIFEST and JAVA EE “lib” folder contents).
Select all the projects, and select from the pop-up menu Maven> Enable Dependency
Management. You will notice added capability to the project.
More details of all these solutions can be found below in the resources section.
Page 25 of 30
SCM integration
Sharing Maven projects requires some understanding of the requirements, or
functionality Rational Application Developer provides in the build lifecycle. Rational
Application Developer integrates with many SCM systems such as IBM Rational
Clearcase and IBM Rational Team Concert. In our example, we will use the CVS client
to demonstrate sharing our projects in Rational Application Developer, and how to
handle physically nested projects, which is the case for the Rational Application
Developer workspace on the Maven machine, but not all developers will need to nest
projects (or have a local Maven repository installed), and can check out projects as folder
siblings. Within Rational Application Developer, the CVS tools allow initially sharing
these projects using a single root, but not nested in the same Maven folder structure. This
requires “ignoring” the nested structures within a composite project. The Team > Share
Project wizard allows creation of the .cvsignore before the initial commit takes place.
For instance, the two utility projects (DataProject and MyCompanyEJBClient) have
already been shared, and the composite project Utilities is now being shared. Selecting
the nested resources and adding to the .cvsignore file will ensure resources are shared
once.
Page 26 of 30
Figure 16: Sharing projects
Page 27 of 30
Rational Application Developer – Rational Team Concert
– Maven integration
Rational Team Concert is a collaborative software delivery environment that helps teams
to simplify, automate and govern software delivery, and is easily integrated into Rational
Application Developer 7.5 using the IBM Installation Manager option shown below
Figure 17: Installation Manager setting
Rational Team Concert includes its own build engine, but also supports many build
platforms such as IBM Rational BuildForge and Maven. To use these build systems, the
Rational Team Concert client must be connected to a Rational Team Concert server and
also use the Build System Toolkit.
Download required prerequisites
If you don’t have a server available, free and trial options are available at the Jazz.net
download site:
(Version 1.0.1.1 (Express-C) was used in this demo) https://jazz.net/downloads/rationalteam-concert/releases/1.0.1.1/
Follow the instructions on how to set up the server and build system toolkit
https://jazz.net/downloads/rational-teamconcert/releases/1.0.1.1?p=install.docs/install_server
Creating a Maven build
In your Rational Application Developer workspace, find the Team Artifacts view, and
expand your project area. Select the builds node, and click New Build Definition. Next
select your team area to associate with the build. Type an ID for the build definition. I
used Test RTC Team Build. Select the Maven - Jazz Build Engine template, and click
Finish. The build definition editor opens. On the General page, in the Supporting Build
Engines section, click Create Engine. Type an engine ID such as "MyBuild". On the
Maven page, enter the project location, goals, and Maven home. My entries are shown in
Figure 18.
Save and close the editor.
Page 28 of 30
Figure 18: Setting up Maven build
Starting the Build Engine
To run Maven builds through Rational Team Concert in Rational Application Developer,
you must start the Jazz Build Engine. This is required because this process will “listen”
for build requests. In this example, we will run it on our local machine.
1. Open a command prompt or shell.
2. cd to installdir/buildsystem/buildengine/eclipse.
3. Run the following command:
jbe -repository address -userId you -pass your_password -engineId
MyBuild -sleeptime 1
Running a Maven build
1. In the definition editor header, click the Request Build button.
2. In the Request Build dialog, click Submit.
3. See Results in Builds Tab.
Figure 29: Build results
These details and more are located on the Jazz wiki site:
https://jazz.net/wiki/bin/view/Main/MavenBuild
Page 29 of 30
Resources
•
•
•
•
•
•
Maven Home: http://maven.apache.org/
WebSphere Application Server information center:
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.
websphere.base.doc/info/welcome_base.html
Rational Application Developer information center:
http://publib.boulder.ibm.com/infocenter/radhelp/v7r5/index.jsp
M2eclipse Home: http://m2eclipse.sonatype.org/
M2eclipse project wiki: http://docs.codehaus.org/display/M2ECLIPSE/Home
Rational Team Concert Home: http://jazz.net/
About the author:
Chuck Bridgham is the lead architect and development manager of the Rational J2EE
Tools team at the IBM Raleigh Lab. This team is responsible for the core developer tools
involved with creating, editing, and assembling Java EE artifacts. Chuck has been an
integral member of many product teams focusing on data, object persistence and Java EE
technologies. Chuck is also the project lead for Java EE Tools on the Eclipse Web Tools
Platform. He can be reached at [email protected]
Page 30 of 30
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement