Я думаю, что ваша проблема в том, что вы открываете входной поток до того, как записали и закрыли выходной поток. Конечно, Sun Tutorial делает это таким образом.
Если вы откроете входной поток слишком рано, возможно, что выходной поток будет автоматически закрыт, в результате чего сервер увидит пустой запрос POST. Этого может быть достаточно, чтобы он запутался и отправил 500 ответов.
Даже если это не то, что вызывает 500 ошибок, было бы неплохо сделать все в порядке, указанном в руководстве. Для начала, если вы случайно прочитали ответ до того, как закончили писать запрос, вы, вероятно, (хотя бы временно) заблокируете соединение. (На самом деле, похоже, что ваш код делает это, потому что вы не закрываете устройство записи перед чтением из устройства чтения.)
Отдельная проблема заключается в том, что ваш код не закрывает соединение при любых обстоятельствах и поэтому может привести к утечке сетевых соединений. Если это будет повторяться, это может привести к большему количеству исключений IOException.