-
Notifications
You must be signed in to change notification settings - Fork 8
Lab Guide, Copilot Java Workshop.
This lab is intended to use GitHub Copilot for Java API and test creation. A familiarity with Java, Maven is required. The repository contains exercise files (exercisefiles) as well as complete solution (completesolution). Navigate to exercisefiles/quarkus/copilot-demo which contains our pom.xml file for maven goals and operations.
Before starting the lab, check the status of GitHub Copilot.
- To complete first task, open the DemoResourceTest.java file to see that we need to have an API with path hello.
- We have already commented the require task in DemoResource.java file. Just open the file and press enter where logic is written as Java Comments.
- GitHub Copilot will pass the context to GitHub LLM and will generate the code as per our logic. P
- As a developer you are the pilot of the project. Please do sanity check and make sure that you understand the code. We can now run the test by issuing maven command
mvn test
- Once our test is successful we can also do the hot deployment on by running the command.
mvn quarkus:dev
- You can now test the new api in the browser by entering URL http://127.0.0.1:8080/hello?key=World. Please make sure that port 8080 is forwarded if you running in GitHub codespaces or in a devcontainer.
In this task we have experienced GitHub Copilot auto completion based on the logic written as comments.
In second task, we will focus on GitHub Copilot Chat.
- Please write this prompt in the Copilot Chat windows. "New operation under /diffdates that calculates the difference between two dates. The operation should receive two dates as parameter in format dd-MM-yyyy and return the difference in days".
- GitHub Copilot Chat will explain what it is generating as a code and will generate the code along with import statements. Please use insert into file icon to insert the code at the cursor location on the right side of coding file, DemoResource.Java.
- As a best practice we do need to create a test case for our newly created method. Again select the method and right click to Copilot->Generate Tests. Copilot will generate the test and will try to automatically locate the Test file for the current java file and on 'accept' click will insert code into the right file.
- You can also ask copilot with the help of directives like @workspace and #file to ask where test cases are defined.
@workspace #file:DemoResource.java where I can define test cases for the class. Also generate 3 test cases for diffDates method.
- GitHub Copilot also tries to complete the processes by understanding the whole context. By keeping DemoResource.Java file open, open the test file and Copilot will automatically try to guess and generate the test methods.
Now we have experienced both ways to interact with copilot. Now let us focus on our prompts. Try different prompts if you are not satisfy with the code generated. Be aware that is generative and not deterministic. So based on your prompts, it will generate the code.
Prompt:
Define a method that validates a Austria phone number. True if valid, false otherwise. Also include error handling for invalid phone number format.
and the generated code is:
/**
* Validates a phone number.
*
* @param phone the phone number to validate
* @return "true" if the phone number is valid, "false" otherwise
*/
@GET
@Path("/validatephone")
@Produces(MediaType.TEXT_PLAIN)
public String validatephone(@QueryParam("phone") String phone) {
Objects.requireNonNull(phone, "phone must not be null");
if (phone.matches("\\+43[0-9]{1,4}")) {
return "true";
} else {
return "false";
}
}
Please also generate the test cases as we did in the last exercise.
Please complete task 4 and 5 as they are very similar to task 3.
Prompt: @workspace #file:DemoResource.java Create a new operation that call the API https://api.chucknorris.io/jokes/random and return the joke. Add error handling and use API Url as variable.
@GET
@Path("/chucknorris")
@Produces(MediaType.TEXT_PLAIN)
public String chucknorris() {
String apiUrl = "https://api.chucknorris.io/jokes/random";
Client client = ClientBuilder.newClient();
WebTarget target = client.target(apiUrl);
Response response = null;
try {
response = target.request(MediaType.APPLICATION_JSON).get();
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.readEntity(String.class));
return root.get("value").asText();
} catch (Exception e) {
e.printStackTrace();
return "Error occurred while fetching joke: " + e.getMessage();
} finally {
if (response != null) {
response.close();
}
client.close();
}
}
Please generate the test case as well.
Given a url as query parameter, parse it and return the protocol, host, port, path and query parameters. The response should be in Json format.
This task is very interesting as we will be calling an external api. Please try different prompts. As its generative AI so, even same prompt could generate different code.
Prompt:
@workspace #file:DemoResource.java create a new operation that take a Given a url as query parameter, parse it and return the protocol, host, port, path and query parameters. The response should be in Json format.
and the generated code is
@GET
@Path("/parseurl")
@Produces(MediaType.APPLICATION_JSON)
public Response parseUrl(@QueryParam("url") String url) {
Objects.requireNonNull(url, "url must not be null");
ObjectMapper mapper = new ObjectMapper();
try {
URL urlNode = new URL(url);
JsonNode root = mapper.createObjectNode();
((ObjectNode) root).put("protocol", urlNode.getProtocol());
((ObjectNode) root).put("host", urlNode.getHost());
((ObjectNode) root).put("port", urlNode.getPort());
((ObjectNode) root).put("path", urlNode.getPath());
((ObjectNode) root).put("query", urlNode.getQuery());
return Response.ok(root).build();
} catch (IOException e) {
e.printStackTrace();
}
// return http 500
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
Test We have also generated the test case using GitHub Copilot.
@Test
public void testParseUrlEndpoint () {
given()
.when().get("/parseurl?url=https://learn.microsoft.com/en-us/azure/aks/concepts-clusters-workloads?source=recommendations")
.then()
.statusCode(200)
.body("protocol", is("https"))
.body("host", is("learn.microsoft.com"))
.body("port", is(-1))
.body("path", is("/en-us/azure/aks/concepts-clusters-workloads"))
.body("query", is("source=recommendations"));
}
@Test
public void testParseUrlEndpointNoUrl () {
given()
.when().get("/parseurl")
.then()
.statusCode(500);
}
We are leaving these task as they are very similar. Please do complete using Prompts.
Use the Dockerfile provided to create a docker image of the application. In this case, the full content is provided, but in order build, run and test the docker image, you will use Copilot as well to generate the commands.
I have created a DOCKER.md file where we will document the steps to build the application (native), build the container image, yun the container and test the container.
In this task, we need to find out the commands that can generate the native docker image of our application and run it.
Prompt 1:
Build a Quarkus native image and the native executable using mvn command
This command is resource intensive. Please make it sure that you have enough resources to complete this. ./mvn package -Pnative
Once you have build the native image, we need to dockerize it.
Prompt 2:
how to build a docker file with Dockerfile.native-micro and name it quarkus-native-micro
docker build -f Dockerfile.native-micro -t quarkus-native-micro .
This command will create the native docker image of our application and will name it as 'quarkus-native-micro'
Prompt 3:
how to run a docker image with image name quarkus-native-micro
docker run -p 8080:8080 quarkus-native-micro
Please test your application by opening it in any browser window.