I have been trying to decipher an Alexa smart home directive API for Java and have encountered a structure I've never seen before and can't figure out how to reference what it is in a search.  I know about generics, but this is different obviously (at least I think).  Can anyone explain to me whats going on in the protected method declaration where <Req extends Request <Res>, Res extends Response> is used?
public abstract class SmartHomeDirectiveHandler implements 
   RequestStreamHandler {
      private static Gson gson = new Gson();
      private static HandlerFactory factory = new HandlerFactory();
   protected <Req extends Request<Res>, Res extends Response> void 
      registerHandler(MessageName name,RequestHandler<Req, Res> handler) {
      factory.registerHandler(name, handler);
   }
   abstract protected void init();
   protected SmartHomeDirectiveHandler() {
      this.init();
   }
   public final void handleRequest(InputStream inputStream, OutputStream 
      outputStream, Context context) throws IOException {
         JsonReader reader = new JsonReader(new 
         InputStreamReader(inputStream));
         SmartHomeDirectiveRequest request = gson.fromJson(reader, 
         SmartHomeDirectiveRequest.class);
         RequestHandler handler = 
         factory.getHandler(request.getHeader().getName());
         Request req = PayloadDeserializer.deserializePayload(request);
         Response responsePayload;
         try {
            responsePayload = handler.handle(req);
         } catch (Exception e) {
            throw new IOException(e);
           }
         SmartHomeDirectiveResponse response = new 
            SmartHomeDirectiveResponse();
         Header responseHeader = new Header();
         responseHeader.setName(responsePayload.getMessageName());
         responseHeader.setMessageId(request.getHeader().getMessageId());
         responseHeader.setPayloadVersion(request.getHeader()
           .getPayloadVersion());
         responseHeader.setNamespace(request.getHeader().getNamespace());
         response.setHeader(responseHeader);
         response.setPayload(responsePayload);
         OutputStreamWriter writer = new OutputStreamWriter(outputStream);
         writer.write(gson.toJson(response, 
         SmartHomeDirectiveResponse.class));
         writer.flush();
      }
   }
 
     
    