Sunday, January 21, 2018

GWT & Spring Security

Sorry this is going to be a quick post without too much detail. But hopefully this will help someone out anyways until I can get to adding detail.

I've been struggling with how to integrate spring security with GWT. I don't have very much experience with using spring security and have been going in circles. After adding spring security with two additional files to configure it, I was able to show a login page and authenticate the user. However, as soon as that happened, the application failed to load because GWT uses POST requests to access the RPC. As it turns out, this isn't a sign that the configuration failed. Spring security expects a CSRF token on post requests to prevent security problems ... GWT doesn't insert this token when accessing the RPC... and so we get a forbidden error. Disabling csrf in the config for spring security is also not working.

I next tried using GWT's XSRF protection ... again I'm not very familiar with web application security. I thought if I did this, then my application would be able to tell spring security the csrf that it expects. This turned into a frustrating chicken and egg issue. To get the XSRF token, gwt does a POST request ... which is blocked by spring security.

Spring security examples that I've found have been for standard web applications, as opposed to GWT's host page mechanism.

I think the final solution is going to be:


  1. Use spring security as a gate keeper to the application
    1. Spring security needs to be configured to override a bunch of things, along the lines of https://crazygui.wordpress.com/2014/08/29/secure-rest-services-using-spring-security/
  2. After authenticated, the application is responsible for maintaining security within itself
    1. We can use the XSRF here for additional security
    2. maintain session information for the authenticated user
So why even use spring security and not just wire up my own login screen etc? Spring security I think will be more flexible and give more options later down the road.



Monday, January 8, 2018

Hibernate exception using match/against sql

*UPDATE*
I finally found the real reason and is quite the facepalm. The keyword "MATCH" is MySql specific. It is not part of the more general Sql syntax. Oops.
----

Apologies that this is going to be a fairly brief post, maybe someday I'll have time to come back and flesh out the details a bit more. But I think this is better than me forgetting to post at all and having this lost in my notes. Hope this helps someone else out.

The problem I've been struggling with is using the "MATCH" sql keyword in hibernate. Specifically, it is failing in my unit test.Below I list the 2 configurations that did not work (A & B) and the full stacktrace. The configuration that does work is to use the mysql driver.

tl;dr: Use MySQL for the database

Code:
final String queryString = "SELECT * FROM Course WHERE MATCH (name) AGAINST ('complex' IN BOOLEAN MODE)";
final Session session = sessionFactory.openSession();
session.beginTransaction();
NativeQuery query = session.createNativeQuery(queryString, Course.class);
List results = query.getResultList();
session.getTransaction().commit();
session.close();

Configuration A:
connection.driver_class = org.h2.Driver
connection.url = dbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
connection.username = root
connection.password = "" 
dialect = org.hibernate.dialect.H2Dialect
hbm2ddl.auto = create

Exception A:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423)
at org.hibernate.query.Query.getResultList(Query.java:146)
at org.catalyst.courses.entities.HibernateTest.searchCoursesQuery(HibernateTest.java:207)
at org.catalyst.courses.entities.CourseTest.testNamedQueries(CourseTest.java:444)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
at org.hibernate.loader.Loader.doQuery(Loader.java:932)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
at org.hibernate.loader.Loader.doList(Loader.java:2615)
at org.hibernate.loader.Loader.doList(Loader.java:2598)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
at org.hibernate.loader.Loader.list(Loader.java:2425)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2160)
at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:992)
at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)
... 28 more
Caused by: org.h2.jdbc.JdbcSQLException: Function "MATCH" not found; SQL statement:
SELECT * FROM Course WHERE MATCH (name) AGAINST ('complex' IN BOOLEAN MODE) [90022-194]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readJavaFunction(Parser.java:2471)
at org.h2.command.Parser.readFunction(Parser.java:2523)
at org.h2.command.Parser.readTerm(Parser.java:2860)
at org.h2.command.Parser.readFactor(Parser.java:2374)
at org.h2.command.Parser.readSum(Parser.java:2361)
at org.h2.command.Parser.readConcat(Parser.java:2331)
at org.h2.command.Parser.readCondition(Parser.java:2166)
at org.h2.command.Parser.readAnd(Parser.java:2138)
at org.h2.command.Parser.readExpression(Parser.java:2130)
at org.h2.command.Parser.parseSelectSimple(Parser.java:2087)
at org.h2.command.Parser.parseSelectSub(Parser.java:1928)
at org.h2.command.Parser.parseSelectUnion(Parser.java:1746)
at org.h2.command.Parser.parseSelect(Parser.java:1734)
at org.h2.command.Parser.parsePrepared(Parser.java:447)
at org.h2.command.Parser.parse(Parser.java:319)
at org.h2.command.Parser.parse(Parser.java:291)
at org.h2.command.Parser.prepareCommand(Parser.java:256)
at org.h2.engine.Session.prepareLocal(Session.java:564)
at org.h2.engine.Session.prepareCommand(Session.java:505)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1204)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)

... 43 more

Root cause A:
MATCH() function is NOT supported by H2 (http://h2-database.66688.n3.nabble.com/MySQL-Compatibility-Mode-Fulltext-MATCH-function-td4033152.html)

Configuration B:

connection.driver_class = org.hsqldb.jdbcDriver
connection.url = jdbc:hsqldb:mem:testdb
connection.username = root
connection.password = "" 
dialect = org.hibernate.dialect.HSQLDialect
hbm2ddl.auto = create

Exception B:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423)
at org.hibernate.query.Query.getResultList(Query.java:146)
at org.catalyst.courses.entities.HibernateTest.searchCoursesQuery(HibernateTest.java:207)
at org.catalyst.courses.entities.CourseTest.testNamedQueries(CourseTest.java:444)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
at org.hibernate.loader.Loader.doQuery(Loader.java:932)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
at org.hibernate.loader.Loader.doList(Loader.java:2615)
at org.hibernate.loader.Loader.doList(Loader.java:2598)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
at org.hibernate.loader.Loader.list(Loader.java:2425)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2160)
at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:992)
at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)
... 28 more
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: MATCH in statement [SELECT * FROM Course WHERE MATCH (name) AGAINST ('complex' IN BOOLEAN MODE)]
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 43 more
Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: MATCH
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.ParserDQL.readColumnOrFunctionExpression(Unknown Source)
at org.hsqldb.ParserDQL.XreadSimpleValueExpressionPrimary(Unknown Source)
at org.hsqldb.ParserDQL.XreadAllTypesValueExpressionPrimary(Unknown Source)
at org.hsqldb.ParserDQL.XreadAllTypesPrimary(Unknown Source)
at org.hsqldb.ParserDQL.XreadAllTypesFactor(Unknown Source)
at org.hsqldb.ParserDQL.XreadAllTypesTerm(Unknown Source)
at org.hsqldb.ParserDQL.XreadAllTypesCommonValueExpression(Unknown Source)
at org.hsqldb.ParserDQL.XreadBooleanPrimaryOrNull(Unknown Source)
at org.hsqldb.ParserDQL.XreadBooleanTestOrNull(Unknown Source)
at org.hsqldb.ParserDQL.XreadBooleanFactorOrNull(Unknown Source)
at org.hsqldb.ParserDQL.XreadBooleanTermOrNull(Unknown Source)
at org.hsqldb.ParserDQL.XreadBooleanValueExpression(Unknown Source)
at org.hsqldb.ParserDQL.readWhereGroupHaving(Unknown Source)
at org.hsqldb.ParserDQL.XreadTableExpression(Unknown Source)
at org.hsqldb.ParserDQL.XreadQuerySpecification(Unknown Source)
at org.hsqldb.ParserDQL.XreadSimpleTable(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryPrimary(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryTerm(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryExpressionBody(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryExpression(Unknown Source)
at org.hsqldb.ParserDQL.compileCursorSpecification(Unknown Source)
at org.hsqldb.ParserCommand.compilePart(Unknown Source)
at org.hsqldb.ParserCommand.compileStatement(Unknown Source)
at org.hsqldb.Session.compileStatement(Unknown Source)
at org.hsqldb.StatementManager.compile(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)

... 47 more

Root Cause B:
:: shrug :: No clue. I've gone cross-eyed trying to figure this out, this should be supported by HSQL. The documentation says it's supported, but I can't figure out what the heck. The only thing I can think is maybe I have the magic SQL incantation incorrect. I didn't want to futz with the query string too much because ultimately the underlying database will be a MySQL database.

Wednesday, January 18, 2017

LG Tablet Frozen on Firmware Update

I've been having a frustrating time with an LG tablet that I got from T-Mobile. The specific model that I have is the V496, also known as LG G Pad X 8.0. The steps to reproduce:

- battery drained completely, cannot be turned on because battery is at 0%
- plug in the tablet to charge
- screen displays (paraphrasing a bit): Firmware updating, do not unplug.
- screen displays a progress bar under the message and the progress bar never progresses

I am fairly certain I have figured out what was causing my issues, and perhaps maybe causing your issues. I was trying to charge from an outlet using the USB cable that came with my XBox. It never occurred to me this could be an issue until it was pointed out that the cable would not charge a Samsung phone. I think there is some extra electronic bits in the connector that is triggering the LG tablet (and possibly other LG equipment) to think it needs a firmware update.

That being said, my tablet was now stuck in an off state since it would not take a charge. To solve this part, I found my solution on this forum, which I will repeat below

  1. Unplug the tablet from the USB cable
  2. Find either a non-branded USB cable or the cable that came with the tablet. In my case, I'm pretty sure I am using the LG USB cable that came with either my LG phone or my LG tablet. Have this cable ready, i.e. one end of it should be plugged into a power source.
  3. Hold down the power button on the tablet for 10 seconds
  4. While still holding down the power, plug the tablet in and then let go of the power button
  5. You should see the outline of a large battery saying 0% for a second and the screen goes blank
  6. Leave the tablet plugged in to complete charging
Thanks for nothing Microsoft 

Friday, October 7, 2016

GWT 2.7.0 and Java 1.8

Well hello there, here's a quick post before I forget of some aggravating "errors" I encountered while trying to compile my code. We currently use GWT 2.7.0 and just upped our code to finally (stop laughing) use Java 1.8. Sounds great right?

Now, to be fair, I'm sure GWT mentions these issues in their documentation... but I'm also sure most of you haven't read through every iota of documentation and probably missed these awesome warnings.

The current warning I get when I compile my GWT module is:

[INFO] Tracing compile failure path for type 'org.eaglei.ui.gwt.search.SearchApplication'
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-search-gwt/4.5.0-SNAPSHOT/eagle-i-search-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/search/SearchApplication.java'
[INFO] [ERROR] org.eaglei.ui.gwt.uiconfig.rpc.SearchUIConfigServiceRemoteAsync cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-search-gwt/4.5.0-SNAPSHOT/eagle-i-search-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/search/common/SearchTopPanel.java'
[INFO] [ERROR] org.eaglei.ui.gwt.search.common.SearchBarWidget cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-search-gwt/4.5.0-SNAPSHOT/eagle-i-search-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/search/SearchApplicationController.java'
[INFO] [ERROR] org.eaglei.ui.gwt.search.SearchApplicationContext cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-common-ui-gwt/4.5.0-SNAPSHOT/eagle-i-common-ui-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/uiconfig/rpc/SearchUIConfigServiceRemoteAsync.java'
[INFO] [ERROR] org.eaglei.services.uiconfig.SearchUIConfig cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-search-gwt/4.5.0-SNAPSHOT/eagle-i-search-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/search/common/SearchBarWidget.java'
[INFO] [ERROR] org.eaglei.ui.gwt.search.SearchApplicationContext cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-search-gwt/4.5.0-SNAPSHOT/eagle-i-search-gwt-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/ui/gwt/search/SearchApplicationContext.java'
[INFO] [ERROR] org.eaglei.services.uiconfig.SearchUIConfig cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-common-services/4.5.0-SNAPSHOT/eagle-i-common-services-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/services/uiconfig/SearchUIConfig.java'
[INFO] [ERROR] org.eaglei.common.util.nodeinfo.NodeConfig cannot be resolved to a type
[INFO] [ERROR] Errors in 'jar:file:/Users/sophia/.m2/repository/org/eagle-i/eagle-i-common-util/4.5.0-SNAPSHOT/eagle-i-common-util-4.5.0-SNAPSHOT-sources.jar!/org/eaglei/common/util/nodeinfo/NodeConfig.java'
[INFO] [ERROR] Line 308: Type mismatch: cannot convert from List to List

So what the crap? I tried googling that last bit about List and only got results about people failing to use generics correctly. That's not my issue, I'm not using generics in this particular block of code.

It turns out it is because of a Java 1.8 enhancement I was using. Instead of:

List thingList = new ArrayList();

You can now omit the second type specifier:

List thingList = new ArrayList<>();

Fantastic!

Except if you use it in one of those fancy schmancy one line tertiary statements. In my code, the offending line of code was:

final List otherInstitutions = (other.getInstitutions() != null) ? other.getInstitutions() : new ArrayList<>();

By specifying the type in the tertiary statement, all was good:

final List otherInstitutions = (other.getInstitutions() != null) ? other.getInstitutions() : new ArrayList();

Yay?

Wednesday, February 19, 2014

Getting Apple Mail's Smart Mailboxes to remember Outlook Exchange folders

I've been trying to get Apple Mail's Smart Mailbox to look inside my Outlook Exchange folders for mail and for whatever reason, the Smart Mailbox doesn't seem to be able to remember the Exchange folder I selected.

For example, I have created a folder named test in my Exchange account.  I then created a Smart Mailbox named Test Mailbox to look at this folder:


After I click OK, and go to edit the Smart Mailbox again:


Ah! Where did my folder go?  I've tried googling various combinations of terms to get information, and I've come across a couple of posts on Apple's forum, but nothing that points to a solution or a workaround.

I initially started down the path of creating a Smart Mailbox with the following filters:
1) Look for Messages not in Mailbox and select Inbox
2) Build a complex filter that is the same as the rules being applied to move messages to the desired folder

It turns out I needed to build some complex filters (combinations of OR and AND) which the dialog doesn't allow for.  The dialog only gives the option of doing one or the other.  I stumbled across this post that helped me build some more complicated filters.

One thing I'd like to point out is that the folder & file name has changed since the post:

[User]/Library/Mail/V2/MailData/SyncedSmartMailboxes.plist

** CAVEAT: Please be sure you back up any of the *.plist files you are going to play with in case things go horribly awry. **

After playing around with this for awhile, I got curious as to why Apple Mail wouldn't remember my folder.  So I re-created the Smart Mailbox named Test Mailbox to look in my Exchange folder test and then I looked in the file and searched for this Smart Mailbox:


And that long garbled string is the problem. For whatever reason, the destination mailbox URL gets completely mangled.

The next thing to do is to find out what the actual destination mailbox URL is.  I happen to have rules in Mail that are applied to incoming messages which filter my email into the various folders.  This file lists these rules:

[User]/Library/Mail/V2/MailData/SyncedRules.plist

I searched this file for my Test folder and found a not garbled URL to my folder:


Copy this URL and paste it in place of that garbled string:


And ta-da!  I now have a Smart Mailbox that is looking inside my Exchange folder.

To summarize:
1) Create a rule that moves emails to the desired folder.
2) Create a Smart Mailbox, as you normally would, pointing to the desired folder and any other conditions.
3) Search the [User]/Library/Mail/V2/MailData/SyncedRules.plist file for the desired folder and look for the CopyToMailboxURL key.
4) Copy the URL under the key.
5) Search the [User]/Library/Mail/V2/MailData/SyncedSmartMailboxes.plist for the new Smart Mailbox.
6) Paste the URL over the garbled string.

Enjoy!

Thursday, December 26, 2013

Xbox One & WPA2 router

Today's post is slightly off topic.  This isn't about any programming .. but a far more important topic .. how to get your xbox one online ;-).  I have my priorities straight.

We spent about 40 minutes repeatedly trying to connect the xbox one to our WPA2 router, doing everything from restarting the console, rebooting the router, using the push button on the admin console for the router ..

The solution? Don't use the auto discovery.

It turns out when you got to network settings, choose 'Add new network' instead of selecting your network from the list.  This will allow you to specify the security, and ta-da .. you're online and can game away.

Happy holidays everyone!

Tuesday, December 10, 2013

Getting eclipse to co-operate with maven & subversion

Oh my, I didn't realize it's been over a year since my last post.  This isn't to imply at all that my past year has been without frustrations.  In fact, I have several stubs for blog posts in my evernote that I just haven't had the time to fully flesh out and put up.  I'll start with today's, since it is very self contained and I have been able to work out a few variations for documenting here.

Today's frustration has been brought to you by maven, subversion and eclipse.

I was first introduced to the notion of having to use eclipse with maven and subversion was several years ago with Eclipse Ganymede.  The sheer pain of having to configure Eclipse to play happily with maven and subversion made me very adverse to updating my Eclipse installation.  In fact, I've waited until updates to features stopped being issued and the features themselves became more or less unsupported.  Point in fact, as of Monday morning, I have been using Eclipse Helios.

Due to some quirkiness in my workspace, I finally decided to bite the bullet and upgrade to Eclipse Kepler.  I had some hiccups getting the correct incantation to have everything work well, but after I repeated the steps a few times (for documentation sake), I can actually say, it's not that painful.

So, to help myself (as well as anyone else floundering) avoid painful eclipse updates, here are the steps for the following configuration:

  • Local (my machine):
    • Eclipse Kepler Release 1 - Java EE
    • Mac OSX Mountain Lion (10.8.5)
  • Server (somewhere in the wild wild web):
    • Maven 3.0.5
    • Subversion 1.6.11
The following documentation assumes a fresh install, with no other extensions/plugins/thingamabobs installed on top of the Eclipse.  Note that in my set up, I do not touch JavaHL with a ten foot pool.  No particular reason except it causes extra confusion, pre-requisites, steps to get it to work.

Also, before we start, there are TWO different options for working with subversion.  I don't have a strong preference for either.  I'm used to Subclipse, but Subversive has prettier icons.

Without further ado, here we go.
  1. Start Eclipse
  2. Help -> Eclipse Marketplace ...
  3. Install Maven Integration
    • ~ EDIT ~
      • If you have installed the Jave EE version of Eclipse, you can skip this step.  Maven Integration is already bundled in. Continue on to step 4.
    • Type in 'Maven Integration' in the search box
    • Scroll down until you find:
      • Maven Integration for Eclipse (Juno and Newer) 1.4
      • eclipse.org, epl
    • Click 'Install'.
    • Do not finish the install yet
    • Click '< Install More'
  4. Install a Subversion solution (NB: There are two options, both are listed)
    • Type in 'Subversion' in the search box
    • Option 1: Subversive
      • Scroll down until you find:
        • Subversive - SVN Provider 1.1.1
        • eclipse.org, epl
      • Click 'Install Now'
      • Break (Go to step 5)
    • Option 2: Subclipse
      • ~ EDIT ~
        • Apparently between writing this up earlier today and now (about 6 hours), there is a new version of Subclipse available via the Marketplace.  For whatever reason, installing this new version (Subclipse 1.10.x) causes an inability to install the SCM connector.
      • Exit the Eclipse Marketplace
      • Install the solution directly:
        • Help -> Install New Software
        • Add a new software style:
          • http://subclipse.tigris.org/update_1.8.x/
      • Go to step 7.
      • Scroll down until you find:
        • Subclipse 1.8.22
        • Subclipse Project, epl
      • Click 'Install Now'
      • Break (Go to step 5)
  5. You will now see screen with a list of all of the items that will be installed for the selected solutions.  
  6. If you are using Option 1: Subversive, there are no additional steps.  All the features should be selected for the two solutions.
  7. If you are using Option 2: Subclipse, you will need to perform an additional step to avoid future headaches.


    • Expand the Subclipse folder
      • Uncheck 'Subversion JavaHL Native Library Adapter'
    • Expand the SCNKit folder
      • Ensure that 'SVNKit Client Adapter' is checked
  1. You will now be prompted to restart eclipse, restart eclipse.


  1. Welcome back! Switch to the 'Java' perspective.  
    • If you don't have the 'Java' perspective as an option, do this:
      • Window -> Open Perspective -> Other... -> Java


  1. Select the 'Package Explorer' view.
    • If you don't have the 'Package Explorer' view, do this:
      • Window -> Show View -> Other... -> Package Explorer
  2. Right click in the empty area and select 'Import'
  3. Filter the import source for 'Maven'
    • Select 'Check out Maven Projects from SCM'
    • Click 'Next >'

  1. Select the m2e Marketplace link
    • NB: This is not the same marketplace as the eclipse marketplace

  1. Scroll down until you see the section 'm2e Team providers'.
    • If you are using Option 1: Subversive (from step 4), select the option that has been highlighted in blue.
      • m2e-subversive
    • If you are using Option 2: Subclipse (from step 4), select the option that has been highlighted in pink.
      • m2e-subclipse
  2. Click 'Finish' and follow the prompts to complete installation. You will be prompted to restart eclipse again, so restart eclipse.
  3. C'est Fin!
You should now be able to check out maven projects from your svn repository.  Enjoy!