Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
The Java Chamber of Horrors
Andreas Zitzelsberger
@andreasz82
QAware
1≅0
if (true == lUsingHttps) {
// ...
}
if (true == lUsingHttps) {
//..
if (lUsingSSLContext) { /* ... */ }
//..
if (true == lUsingHttps) {
if (true == lUsingSSLC...
„true".equals(request.getParameter("statsRequired"))
? true: false
Make the result
extra-boolean
If only there was a
parse...
if (dateCache.after(dateUser) || dateCache.equals(dateUser)) {
return false;
} else {
return true;
}
if (dateCache.after(dateUser) || dateCache.equals(dateUser)) {
return true;
} else {
return false;
}
Strings!
if (clazz != null) {
header.concat(LayoutConst.CLASS_NAME_STR);
header.concat(clazz.getName());
header.concat(LayoutConst....
public final static String NAME = new String("PIE DIAGRAM");
String surplus = new String(" ");
new String(Long.toString(ri...
Objects.equals(
query.getHost(),
hostName)
Which of these are equal?
• Localhost
• LoCaLhOsT
• localhost.localdomain
• 127...
Exceptional
exception
handling
} catch (Exception ex) {
throw ex;
}
} catch (Exception e) {
// improbable exceptions, throw a runtime exception
// to avoid the declaration in the method-sign...
} catch (Exception ex) {
// this exception will be ignored
// because it cannot be sensibly handled
;
} Why is there a
sem...
} catch (SQLException sqlException) {
; // to be compliant with rule NoEmptyCatchBlocks
}
Ah, that’s why!
try {
Thread.sleep(retryWaitTime);
} catch (InterruptedException e) {
; // nothing to do
}
Unless you want your
thread to ...
try {
nextLogger.setLogger(
logManager.currentLogger(nextLoggerName));
loggerTable.remove(nextLoggerName);
} catch (Throwa...
@SuppressFBWarnings(value=„REC_CATCH_EXCEPTION“,
justification="silly rule")
Security!
HttpServletResponseWrapper {
/* ... */
public void setHeader(String arg0, String arg1) {
// in this case do nothing here,
...
public class PasswordEncryptor {
private static final byte[] ALGO = new byte[]{68, 69, 83};
public static String encrypt(S...
Misoverengineerin
g!
public class ServiceInvocationHandler implements InvocationHandler {
private final BusinessService underlyingBusinessServi...
public Object invoke(final Object proxy, final Method method,
final Object[] args) throws Throwable {
try {
if (caller == ...
if (caller == null)
delegate.commit();
if (delegate instanceof ServiceWithAssociatedThread
&& ((ServiceWithAssociatedThrea...
} catch (final Throwable throwable) {
Logger.error(ServiceInvocationHandler.class,
„Error ...", throwable);
if (caller == ...
Integration
Business
What (probably) has happened
Presentation
Service Service Service
Transaction Facade
The setting:
A massive custom framework for
web apps.
Think JEE built in-house
protected void reset() {
String[] classesForReset =
{
„com.acmecorp...legitimaton...XService",
„com.acmecorp...legitimaton...
for (int i = 0; i < classesForReset.length; i++) {
try {
Class class = class.forName(classesForReset[i]);
Method method = ...
How bad can it be?
public static void reset() {
ldapFilters = new HashMap();
}
Filters for per-
user LDAP
queries
public s...
What (probably) has happened
• Stored session state in static variables (maybe a former C programmer?)
• We need a reset()...
What language do you want to
have bad code in?
Thank you!
@andreasz82
Bonus:
More bad code
private static void copyHashMap(HashMap<String,String> source, HashMap<String,String> destination) {
if ((source != null) ...
return super.isIdentical(msg) && germanMsg != null ?
germanMsg.getMsg().equals(msg.getMsg(Locale.GERMAN)):
true && default...
public AcmeCorpInteger(int intValue) {
this();
try {
setValue(new BigInteger("" + intValue));
} catch (AcmeCorpDatatypeCon...
Integer enterpriseNo = new Integer(
enterpriseDTO.getEnterpriseNo().getValue().intValue());
setCookie(
(new Long(userSession.getAccessTime())).toString(),
response);
public URLConnection(String[] urls, int maxRetries, long waitMs) {
super(getUrlFromString(urls[0]));
if ((null == urls) ||...
The Java Chamber of Horrors
Upcoming SlideShare
Loading in …5
×

The Java Chamber of Horrors

653 views

Published on

DEVOXX UK 2019, London: Talk by Andreas Zitzelsberger (@andreasz82, Principal Software Architect at QAware)

=== Please download slides if blurred! ===

Watch the full talk on YouTube: https://www.youtube.com/watch?v=Gcwlt6_uhQU

Abstract:
There’s good code, and there’s bad code. There also is code so spectacularly bad that it leaves a lasting impression. This talk will show some of the most egregious code from several years of developing software so that we may learn from the mistakes of the past and be entertained.
All code is real (but anonymized) and ran in production.

Published in: Software
  • Be the first to like this

The Java Chamber of Horrors

  1. 1. The Java Chamber of Horrors Andreas Zitzelsberger @andreasz82 QAware
  2. 2. 1≅0
  3. 3. if (true == lUsingHttps) { // ... }
  4. 4. if (true == lUsingHttps) { //.. if (lUsingSSLContext) { /* ... */ } //.. if (true == lUsingHttps) { if (true == lUsingSSLContext) { /* ... */ } } // ... } Better double check! Interleave control flows
  5. 5. „true".equals(request.getParameter("statsRequired")) ? true: false Make the result extra-boolean If only there was a parseBoolean method
  6. 6. if (dateCache.after(dateUser) || dateCache.equals(dateUser)) { return false; } else { return true; }
  7. 7. if (dateCache.after(dateUser) || dateCache.equals(dateUser)) { return true; } else { return false; }
  8. 8. Strings!
  9. 9. if (clazz != null) { header.concat(LayoutConst.CLASS_NAME_STR); header.concat(clazz.getName()); header.concat(LayoutConst.NEW_LINE); } Early implementation of github.com/kelseyhightower/noco de
  10. 10. public final static String NAME = new String("PIE DIAGRAM"); String surplus = new String(" "); new String(Long.toString(rightPoint)); new String("col" + String.valueOf(z + 2)); Me want objects! GC
  11. 11. Objects.equals( query.getHost(), hostName) Which of these are equal? • Localhost • LoCaLhOsT • localhost.localdomain • 127.0.0.1 • 127.0.0.2 • 192.168.178.5 • my-computer • my-computer.my-domain
  12. 12. Exceptional exception handling
  13. 13. } catch (Exception ex) { throw ex; }
  14. 14. } catch (Exception e) { // improbable exceptions, throw a runtime exception // to avoid the declaration in the method-signature throw new RuntimeException( "... failed", e); }
  15. 15. } catch (Exception ex) { // this exception will be ignored // because it cannot be sensibly handled ; } Why is there a semicolon?
  16. 16. } catch (SQLException sqlException) { ; // to be compliant with rule NoEmptyCatchBlocks } Ah, that’s why!
  17. 17. try { Thread.sleep(retryWaitTime); } catch (InterruptedException e) { ; // nothing to do } Unless you want your thread to be able to shut down …
  18. 18. try { nextLogger.setLogger( logManager.currentLogger(nextLoggerName)); loggerTable.remove(nextLoggerName); } catch (Throwable t) { failed = true; }
  19. 19. @SuppressFBWarnings(value=„REC_CATCH_EXCEPTION“, justification="silly rule")
  20. 20. Security!
  21. 21. HttpServletResponseWrapper { /* ... */ public void setHeader(String arg0, String arg1) { // in this case do nothing here, // because we are setting it in the filter } public void setContentType(String arg0) { // in this case do nothing here, // because we are setting it in the filter } Breaks contract of HttpServletResponse
  22. 22. public class PasswordEncryptor { private static final byte[] ALGO = new byte[]{68, 69, 83}; public static String encrypt(String str) throws BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException { // ... Cipher cipher = Cipher.getInstance(new String(ALGO)); cipher.init(1, new SecretKeySpec(key, new String(ALGO))); // ... } } D E S
  23. 23. Misoverengineerin g!
  24. 24. public class ServiceInvocationHandler implements InvocationHandler { private final BusinessService underlyingBusinessService; private final BusinessService derivedFromBusinessService; public Object invoke(/* ... */ ) throws Throwable { /* ... */ } public static Object getService(/* ... */) { /* ... */ } } Let’s call these delegate and caller for the sake of clarity…
  25. 25. public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { try { if (caller == null) delegate.setSession(HibernateUtil.getSessionFactory() .getCurrentSession()); else { Assert.isNotNull(caller.getSession()); delegate.setSession(caller.getSession()); } delegate.beginTransaction(); final Object ret = method.invoke(delegate, args); // continued ... No Caller → New Hibernate session Otherwise, use the caller’s session Wait, what if there already is an open transaction?
  26. 26. if (caller == null) delegate.commit(); if (delegate instanceof ServiceWithAssociatedThread && ((ServiceWithAssociatedThread) delegate) .hasAssociatedThread()) { ((ServiceWithAssociatedThread) delegate) .startAssociateThread(); ((ServiceWithAssociatedThread) delegate) .removeAssociateThread(); } return ret; } catch (final Throwable throwable) { // continued … } Unfinished transaction if there is a caller What could go wrong?
  27. 27. } catch (final Throwable throwable) { Logger.error(ServiceInvocationHandler.class, „Error ...", throwable); if (caller == null && delegate.hasTransaction()) delegate.rollback(); else if (caller != null && caller.hasTransaction()) caller.rollback(); throw throwable.getCause(); } finally { if (delegate.hasSession()) { //if (caller != null) // delegate.close(); delegate.setSession(null); } Wait, what? Wait for the GC to clean up after us Modify stack trace, possible NullPointerException
  28. 28. Integration Business What (probably) has happened Presentation Service Service Service Transaction Facade
  29. 29. The setting: A massive custom framework for web apps. Think JEE built in-house
  30. 30. protected void reset() { String[] classesForReset = { „com.acmecorp...legitimaton...XService", „com.acmecorp...legitimaton...YService", "com.acmecorp...legitimaton...ZService", // ... }; // continued ... Boss music starts…
  31. 31. for (int i = 0; i < classesForReset.length; i++) { try { Class class = class.forName(classesForReset[i]); Method method = class.getDeclaredMethod( „reset", new Class[0]); method.invoke(null, null); } catch Exception e) { System.err.println(/* ... */); e.printStackTrace(System.err); } } Call a static reset method on each class for each request
  32. 32. How bad can it be? public static void reset() { ldapFilters = new HashMap(); } Filters for per- user LDAP queries public static void reset() { sslSocketFactory = null; } New connections for each request
  33. 33. What (probably) has happened • Stored session state in static variables (maybe a former C programmer?) • We need a reset() method, but it has to be static • Can’t use an interface for static methods • Call them by reflection • Forget about this code and have it run in production... • ...for over 10 years • ...in almost 300 applications
  34. 34. What language do you want to have bad code in?
  35. 35. Thank you! @andreasz82
  36. 36. Bonus: More bad code
  37. 37. private static void copyHashMap(HashMap<String,String> source, HashMap<String,String> destination) { if ((source != null) && (destination != null)) { if (!destination.isEmpty()) { destination.clear(); } for(HashMap.Entry<String, String> entry: source.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); destination.put(new String(key), new String(value)); } } }
  38. 38. return super.isIdentical(msg) && germanMsg != null ? germanMsg.getMsg().equals(msg.getMsg(Locale.GERMAN)): true && defaultMsg != null ? defaultMsg.getMsg().equals(msg.getMsg(DEFAULT_LOCALE)): true;
  39. 39. public AcmeCorpInteger(int intValue) { this(); try { setValue(new BigInteger("" + intValue)); } catch (AcmeCorpDatatypeConditionError ex) { } }
  40. 40. Integer enterpriseNo = new Integer( enterpriseDTO.getEnterpriseNo().getValue().intValue());
  41. 41. setCookie( (new Long(userSession.getAccessTime())).toString(), response);
  42. 42. public URLConnection(String[] urls, int maxRetries, long waitMs) { super(getUrlFromString(urls[0])); if ((null == urls) || (urls.length <= 0)) { throw new RuntimeException("empty urls"); } // ... } //NOBUG //Only to satisfy constructor

×