Friday Mar 22, 2013

Introducing Kids to Java Programming Using Minecraft


Minecraft is a wildly popular game among elementary and middle schoolers. The game allows players to build constructions of textured cubes in a 3D world.

My son has been playing the game for about a year, lets say addicted to it. Last Fall he told me that the game is corrupted because the JAR file snapshot has messed up the configuration. And that right away rang a bell in me as a Java Evangelist at Oracle.

I learned from him that the game is written in Java, has a trial version that runs as an applet in the browser, and downloaded as a JAR file for desktop. The game is modular where the players travel through a world and chunks are loaded and unloaded to keep the memory footprint small. Something unique about the game is the ability to modify the game from what it was originally designed for. In Minecraft language, this is called as a "mod" - short for modifications. For example, a mod can add new characters to the game, change look-and-feel of the play field, or make it easy to build new structures.

The game has a server and a client component. This allows the game to be played in a single player mode where a player connects to a server using a client and plays the game. Alternatively multiple players, using different clients across platforms, can connect to a server and play with each other collaboratively. Its very common to have a server run with multiple mods. There are almost an infinite number of mods someone could do to make Minecraft a more amusing game to play. There is no official API to create these mods but there are several third-party vendors that provide that capability; Bukkit is one such API. The ability to write mods and alter the game play gives players more control over the game and gets them more excited.

My son expressed his desire to write a mod and so we started exploring further. Then onwards, he started teaching me Minecraft vocabulary and I taught him the Java programming concepts. Our discussions in the car, on the dinner table, during the breakfast preparation, and elsewhere changed to reflect that as well. He already played with Scratch and Greenfoot last Summer and that was extremely helpful during this learning curve. We set up a goal to build a mod during Christmas break. After understanding the basic concepts and building a few mods, we decided to share the knowledge with a broader set of Minecrafters. And that's where the concept of doing a Minecraft Workshop was born.

My son came up with a list of his minecraft buddies and we announced a date for the workshop. Everybody invited for the workshop confirmed their presence right away. I found out that both the invited kids and their parents were equally excited. One friend could not attend because of a prior commitment and was extremely disappointed. On the day of the workshop, some kids were eager to come even before the formal start of the workshop.

The workshop was attended by 10 kids with age ranging from 10-14 years. Most of the kids had no programming experience, let alone Java. However there was high Minecraft experience in the group with some kids playing for about 2 years and up to 2 hours every day. When given the topic of Minecraft, the small group would talk excitedly about different aspects of the game, constantly using hundreds of game-specific terms and phrases as if speaking a different language. My goal was to leverage their passion and introduce them to Java programming.


The challenge for me was to introduce programming to these kids using analogies from the daily life. Using a car, features, capabilities, types, and car dealers and correlating with class, properties, methods, instances, and packages seem to work. Fruits and different methods of peeling, eating, and planting was used to introduce the concept of Interface in Java. I asked, “What can you do with a watermelon?” the first answer was obvious, “you can eat it.” The second one was a little less so, “You can chuck in a trash can.” The response was greeted with scattered laughter. I used that to explain the concept of Exceptions in Java.

Short anecdotes and side-conversations kept the livelihood of the group going throughout the five hour programming session. There are almost an infinite number of mods someone could do to make Minecraft a more amusing game to play. But all these mods hold the same basic framework that we set up for any future work on making game-specific mods. By the end of the session, we had worked out an entire framework for making a mod. A Maven archetype to create a template Bukkit plugin allowed the attendees to avoid writing boilerplate code. A lower bar to get started and simplicity was the key for this audience. The mod built in the workshop added a new server-side command and printed a trivial message.

Although the goal of the workshop was to get an introduction on programming and make a Minecraft mod, I believe the attendees learned much more than that. I think the informal set up helped them discover that programming can be fun and useful to add to gaming experience. Programming is a vast field and we barely scratched the surface. But most importantly, the attendees had a good time and learned their first lesson of Java programming to start off an interest in it.


"Fun", "Easy", "Quick", "Awesome", "Short", and "Intuitive" described attendees' one word summary of building and running their first Hello World application using NetBeans.

All the instructions followed in the workshop, including a lot more pictures, are available at java4kids.java.net/minecraft-workshop.

For me, it was quite a humbling and learning experience. I've delivered multiple workshops all around the world but mostly to professional developers. I realized how the instructions need to be completely spelled out in order for the attendees of this age to make progress. Something as simple as "Hit Enter after entering the command", yes, that is required. Anyway I plan this to be the first of many more workshops aimed to introduce the world of Java programming to school students.

One of the lessons learned during the workshop was to simplify the installation experience. All the kids had JDK and NetBeans set up already, pretty straight forward. However I wonder why Maven insists on JAVA_HOME variable instead of figuring it out. I need to investigate how to seamlessly install JDK, NetBeans, and Maven in a platform independent way. This will allow to focus more on building the actual mod rather than the multi-step installations.



This workshop was not possible without mentoring support from Allen Dutra and other parents. A huge shout out to my family who helped validate and calibrate my strategy for the audience. My nephews feedback from the lab is incorporated into this blog. Thanks to Oracle for sponsoring the snacks!

Thank you @notch for using Java to build the game! You've provided a great platform for young kids to learn Java and truly enabled Make The Future Java ...

Wednesday Mar 06, 2013

Chunked Step using Batch Applications in Java EE 7: Getting Started with GlassFish 4 (TOTD #211)


TOTD #192 explained the key concepts of JSR 352. This Tip Of The Day provides a working example of a how to write a simple chunk step using JSR 352 Reference Implementation integrated in GlassFish 4.

The source code for this sample application can be downloaded from here and works on GlassFish 4 b78.

As explained in TOTD #192, JSR 352 defines item-oriented processing using chunk step and task-oriented processing using batchlet step. A chunk consists of a reader that reads one item at a time, a processor that processes one item at a time, and a writer that aggregates 'chunk' number of items and then writes them out.

Here is an implementation of reader:

@Named
public class MyItemReader extends AbstractItemReader<MyInputRecord> {
   
    private final StringTokenizer tokens;
   
    public MyItemReader() {
        tokens = new StringTokenizer("1,2,3,4,5,6,7,8,9,10", ",");
    }
   
    @Override
    public MyInputRecord readItem() {
        if (tokens.hasMoreTokens()) {
            return new MyInputRecord(Integer.valueOf(tokens.nextToken()));
        }
        return null;
    }
}

Reader uses type information to specify the type of record that it is working on, MyInputRecord in this case. The readItem method returns null to indicate the end of items that can be read. In this case, a StringTokenizer is used to read the items but you can use an InputStream here if you like.

Here is an implementation of processor:

@Named
public class MyItemProcessor implements ItemProcessor<MyInputRecord,MyOutputRecord> {

    @Override
    public MyOutputRecord processItem(MyInputRecord t) {
        System.out.println("processItem: " + t);
       
        return (t.getId() % 2 == 0) ? null : new MyOutputRecord(t.getId() * 2);
    }
}

Processor uses type information to specify the type of input and output records its working on, MyInputRecord is the input record and MyOutputRecord is the output record in this case. The processItem method reads the input record and accepts only odd-numbered records. This is where your business logic would be implemented.

And here is an implementation of writer:

@Named
public class MyItemWriter extends AbstractItemWriter<MyOutputRecord> {

    @Override
    public void writeItems(List<MyOutputRecord> list) {
        System.out.println("writeItems: " + list);
    }
}

Writer uses type information as well to specify the type of output record, MyOutputRecord in this case. All these elements are tied together using "Job XML" as shown:

<job id="myJob" xmlns="http://batch.jsr352/jsl">
    <step id="myStep" >
        <chunk item-count="3">
            <reader ref="myItemReader"></reader>
            <processor ref="myItemProcessor"></processor>
            <writer ref="myItemWriter"></writer>
        </chunk>   
    </step>
</job>


Eventually, the references myItemReader, myItemProcessor, and myItemWriter will be resolved using CDI. But for now, the references can be explicitly resolved using "batch.xml" as shown:

<batch-artifacts xmlns="http://jcp.org.batch/jsl">
    <ref id="myItemReader" class="org.glassfish.chunk.simple.MyItemReader"/>
    <ref id="myItemProcessor" class="org.glassfish.chunk.simple.MyItemProcessor"/>
    <ref id="myItemWriter" class="org.glassfish.chunk.simple.MyItemWriter"/>
</batch-artifacts>


Once again, downloaded the source code from here and get it running on GlassFish 4 b78.

Post feedback on public@jbatch.java.net or users@glassfish.java.net.


Monday Mar 04, 2013

Consuming and Producing JSON using JAX-RS Entity Providers and JSR 353 Streaming API (TOTD# 210)


TOTD #193 explained how JAX-RS Entity Providers can be used to provide mapping between on-the-wire representations and their associated Java types. This blog shows how you can use Java API for JSON Processing (JSR 353), already integrated in GlassFish 4 promoted builds, to produce and consume JSON payload using Entity Providers.

The source code in this blog can be downloaded here and runs on GlassFish b76.

Lets say your domain object is defined as:

public class MyObject {

  private String name;
  private int age;

  //. . .
}

And your resource endpoint is defined as:

@Path("endpoint")
public class MyResource {
  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  public MyObject echoObject(MyObject mo) {
    return mo;
  }
}

This is just echoing the domain object but I suspect your domain logic would be more complex than that ;-)

Using JAX-RS Client API, this endpoint can be invoked as:

WebTarget target = client.target(".../endpoint");
MyObject mo = target
               .request()
               .post(
                 Entity.entity(new MyObject("Duke", 18), MediaType.APPLICATION_JSON),
                 MyObject.class);
System.out.println("Received response: " + mo.getName() + ", " + mo.getAge() + "<br><br>");

The MessageBodyWriter.writeTo method, that writes MyObject to the underlying OutputStream, uses Streaming API from JSR 353 and looks like:

@Override
public void writeTo(MyObject t,
                    Class<?> type,
                    Type type1,
                    Annotation[] antns,
                    MediaType mt,
                    MultivaluedMap<String, Object> mm,
                    OutputStream out)
            throws IOException, WebApplicationException {
  JsonGeneratorFactory factory = Json.createGeneratorFactory();
  JsonGenerator gen = factory.createGenerator(out);
  gen.writeStartObject()
     .write("name", t.getName())
     .write("age", t.getAge())
     .writeEnd();
  gen.flush();
}

Similarly MessageBodyReader.readFrom method, that reads MyObject from the underlying InputStream, uses Streaming API from JSR 353 and looks like:

@Override
public MyObject readFrom(Class<MyObject> type,
                         Type type1,
                         Annotation[] antns,
                         MediaType mt,
                         MultivaluedMap<String, String> mm,
                         InputStream in)
                throws IOException, WebApplicationException {
  MyObject mo = new MyObject();
  JsonParser parser = Json.createParser(in);
  while (parser.hasNext()) {
    switch (parser.next()) {
      case KEY_NAME:
        String key = parser.getString();
        parser.next();
        switch (key) {
          case "name":
            mo.setName(parser.getString());
            break;
          case "age":
            mo.setAge(parser.getIntValue());
            break;
          default:
            break;
        }
        break;
      default:
        break;
    }
  }
  return mo;
}

The code is pretty straight forward and refer to Java API for JSON Processing javadocs if you need help in understanding the code.

Download the source code and enjoy!
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« March 2013 »
SunMonTueWedThuFriSat
     
1
2
3
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
31
      
Today