Java, write once, run away!

This blog is mainly about Java...

Friday, February 24, 2017

java.sql.SQLException: Protocol Violation [14, 62]

Apparently there is a bug in OJDBC 7 Oracle Driver version 12.1.0.1.0.
Take a look at https://confluence.atlassian.com/confkb/confluence-and-oracle-fail-with-protocol-violation-and-could-not-get-clob-value-for-col-errors-780863295.html

The stacktrace in question is this:
Caused by: java.sql.SQLException: Protocol Violation [ 14, 62, ]
 at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:669) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.T4C8TTIClob.read(T4C8TTIClob.java:245) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.T4CConnection.getChars(T4CConnection.java:3901) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.sql.CLOB.getChars(CLOB.java:517) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.sql.CLOB.getSubString(CLOB.java:354) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.ClobAccessor.getString(ClobAccessor.java:454) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.GeneratedStatement.getString(GeneratedStatement.java:327) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at oracle.jdbc.driver.GeneratedScrollableResultSet.getString(GeneratedScrollableResultSet.java:882) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
 at org.springframework.jdbc.support.lob.DefaultLobHandler.getClobAsString(DefaultLobHandler.java:181) ~[spring-jdbc-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
 at no.gjensidige.bank.datavarehus.debt.DebtApplication.lambda$run$0(DebtApplication.java:63) [classes!/:0.3]
 at no.gjensidige.bank.datavarehus.debt.DebtApplication$$Lambda$7.328FAEA0.mapRow(Unknown Source) ~[na:na]
 at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93) ~[spring-jdbc-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
 at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60) ~[spring-jdbc-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
 at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:697) ~[spring-jdbc-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
 at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633) ~[spring-jdbc-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
 ... 20 common frames omitted



There are 3 actions that can be taken to avoid this bug:

  1. Use the JDBC driver version 12.1.0.2.0 which seems to fix this bug
  2. Install the patch provided in the Oracle support page. (this is only available to customers with a valid Oracle support license). Download and apply Patch 17976703 from Support Portal -> Patches & Updates Section.
  3. Switch back to the OJDBC 6 driver which doesn't have this bug.

Thursday, September 10, 2015

20 tips to reach your goals!

Here is my talk on #JavaZone with the title "20 tips to reach your golas". Hope you benefit from it!

20 tips to reach your goals! from JavaZone on Vimeo.

Tuesday, March 17, 2015

Get Location headers from response in AngularJS and Dropwizard

You have googled and found out that
 headers('Location')  
is the method to use to get the location?
But you always get undefined?
But in your developer tools you can see the Location in the header?

Perhaps you are using CORS (Cross Origin Resource Sharing)?
Enabling CORS only exposes a small number of the available headers by default and if you want more you have to expose them your self.

Use the ExposedHeaders
 // Enable CORS headers  
 FilterRegistration.Dynamic cors = environment.servlets().addFilter("CORS", CrossOriginFilter.class);  
 // Configure CORS parameters  
 cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");  
 cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");  
 cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,PUT,POST,DELETE,HEAD");  
 cors.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");  
 cors.setInitParameter(CrossOriginFilter.EXPOSED_HEADERS_PARAM, "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin,Location")
 // Add URL mapping  
 cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");  

Note the highlighted line. That did the trick!

Thursday, July 19, 2012

Unit testing with JOptionPane

If you are like me, you would still like to be able to unit test your swing applications.

However, its difficult to do this when you have a JOptionPane.showConfirmationDialog, and the user needs to type in yes or no.

In this blog post I will show you how you can accomplish this without needing the user to add anything, or changing your domain code too much.


Lets say you have a simple JFrame you want to test that contains a JOptionPane.


public class SimpleFrame extends JFrame {

  public boolean simpleMethod() {
    int showConfirmDialog = JOptionPane.showConfirmDialog(this, "Can we write test for this?", "Question", JOptionPane.YES_NO_OPTION);
    return showConfirmDialog == JOptionPane.YES_OPTION;
  }
}


Now if you create a JUnit test for this, and run it, you will get a JOptionPane and you need to press the YES or NO button.

To avoid this we can change the code to use an interface and then we can create a mock OptionPane for you tests.



/*
* Note you can add all the methods you use in your application
*/
public interface OptionPane {

      /**
       *  @see JOptionPane#showConfirmDialog(Component, Object, String, int, int);
       */
      int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType);
}


Create three implementations of this interface. One that is delegating to JOptionPane, and the others that will be our mock. One of the mocks will return yes, the other no.


public class DefaultOptionPane implements OptionPane {

      public int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) {
         return JOptionPane.showConfirmDialog(parentComponent,message,title,optionType,messageType);
      }
}

public class YesMockOptionPane extends MockOptionPane {

        @Override
 public int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) {
   return JOptionPane.YES_OPTION;
 }
}


public class NoMockOptionPane extends MockOptionPane {

        @Override
 public int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) {
   return JOptionPane.NO_OPTION;
 }
}



Now change your application and add the OptionPane


public class SimpleFrame extends JFrame {
  private OptionPane optionPane = DefaultOptionPane();
  
  public boolean simpleMethod() {
    int showConfirmDialog = optionPane.showConfirmDialog(this, "Can we write test for this?", "Question", JOptionPane.YES_NO_OPTION);
    return showConfirmDialog == JOptionPane.YES_OPTION;
  }

  public void setOptionPane(OptionPane o) { this.optionPane = o; }
}


Now in your tests you use the appropriate MockOptionPane.



@Test
public void test() throws Exception {
  SimpleFrame s = new SimpleFrame()
  s.setOptionPane(new YesMockOptionPane());
  Assert.assertTrue(s.simpleMethod());
}

Thursday, June 7, 2012

Always use unique passwords!

Recently we found out that LinkedIn has managed to loose our passwords, so that they encourage people to create new passwords.

And if you are like many others, you have the same password for other sites. With a very easy trick you can guarantee a unique password for all your sites, and its quite easy.
All you have to do is remember an easy formula which you decide.

The formula is:
followed by the first three (or last three) letters in the url. You can combine this to put it before or after your password.

So for LinkedIn for instance it would be: lin or din or lin or din

By doing this, you don't have to login to all the other sites and change your password if your password ever gets compromised.

Labels