tag:blogger.com,1999:blog-25875815143213221992024-03-13T07:34:03.854-04:00Misadventures of an Over-caffeinated Frog...I know a little bit about a lot of different programming languages and stuff, but sometimes, I don't know enough and find myself searching the interweb in circles for what should be a simple answer. This is a compilation of the fruits of these searches in hopes that will help some one out there that has similar questions/issues/problems and maybe save them a little bit of time. :)
Obligatory opinions my own they are.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-2587581514321322199.post-74560387406616484612018-01-21T16:24:00.000-05:002018-01-21T16:24:19.433-05:00GWT & Spring SecuritySorry 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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
Spring security examples that I've found have been for standard web applications, as opposed to GWT's host page mechanism.<br />
<br />
I think the final solution is going to be:<br />
<br />
<br />
<ol>
<li>Use spring security as a gate keeper to the application</li>
<ol>
<li>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/</li>
</ol>
<li>After authenticated, the application is responsible for maintaining security within itself</li>
<ol>
<li>We can use the XSRF here for additional security</li>
<li>maintain session information for the authenticated user</li>
</ol>
</ol>
<div>
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.</div>
<div>
<br /></div>
<br />
<br />Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-58653753416591135332018-01-08T17:31:00.002-05:002018-05-18T13:57:57.804-04:00Hibernate exception using match/against sql<span style="font-family: inherit;"><b>*UPDATE*</b></span><br />
<span style="font-family: inherit;">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.</span><br />
<span style="font-family: inherit;">----</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">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.</span><br />
<span style="font-family: inherit;"><br />
</span> <span style="font-family: inherit;">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.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">tl;dr: Use MySQL for the database</span><br />
<br />
<b>Code:</b><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">final String queryString = "SELECT * FROM Course WHERE MATCH (name) AGAINST ('complex' IN BOOLEAN MODE)";</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">final Session session = sessionFactory.openSession();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">session.beginTransaction();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">NativeQuery<course> query = session.createNativeQuery(queryString, Course.class);</course></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">List<course> results = query.getResultList();</course></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">session.getTransaction().commit();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">session.close();</span><br />
<br />
<b>Configuration A:</b><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.driver_class = org.h2.Driver</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.url = dbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.username = root</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.password = "" </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">dialect = org.hibernate.dialect.H2Dialect</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">hbm2ddl.auto = create</span><br />
<br />
<b>Exception A:</b><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small; white-space: pre;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.Query.getResultList(Query.java:146)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.catalyst.courses.entities.HibernateTest.searchCoursesQuery(HibernateTest.java:207)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.catalyst.courses.entities.CourseTest.testNamedQueries(CourseTest.java:444)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at java.lang.reflect.Method.invoke(Method.java:498)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.run(ParentRunner.java:363)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runner.JUnitCore.run(JUnitCore.java:137)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doQuery(Loader.java:932)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doList(Loader.java:2615)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doList(Loader.java:2598)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.list(Loader.java:2425)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2160)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:992)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>... 28 more</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Caused by: org.h2.jdbc.JdbcSQLException: Function "MATCH" not found; SQL statement:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">SELECT * FROM Course WHERE MATCH (name) AGAINST ('complex' IN BOOLEAN MODE) [90022-194]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.message.DbException.get(DbException.java:179)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.message.DbException.get(DbException.java:155)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readJavaFunction(Parser.java:2471)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readFunction(Parser.java:2523)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readTerm(Parser.java:2860)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readFactor(Parser.java:2374)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readSum(Parser.java:2361)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readConcat(Parser.java:2331)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readCondition(Parser.java:2166)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readAnd(Parser.java:2138)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.readExpression(Parser.java:2130)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parseSelectSimple(Parser.java:2087)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parseSelectSub(Parser.java:1928)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parseSelectUnion(Parser.java:1746)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parseSelect(Parser.java:1734)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parsePrepared(Parser.java:447)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parse(Parser.java:319)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.parse(Parser.java:291)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.command.Parser.prepareCommand(Parser.java:256)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.engine.Session.prepareLocal(Session.java:564)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.engine.Session.prepareCommand(Session.java:505)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1204)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)</init></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>... 43 more</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br />
</span> <span style="font-family: inherit;"><b>Root cause A:</b></span><br />
<span style="font-family: inherit;"><i>MATCH() function is NOT supported by H2 (</i><i>http://h2-database.66688.n3.nabble.com/MySQL-Compatibility-Mode-Fulltext-MATCH-function-td4033152.html)</i></span><br />
<span style="font-family: inherit;"><span style="font-family: "verdana" , sans-serif;"><i><br />
</i></span> <span style="font-family: "verdana" , sans-serif;"><b>Configuration B:</b></span></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.driver_class = org.hsqldb.jdbcDriver</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.url = jdbc:hsqldb:mem:testdb</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.username = root</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">connection.password = "" </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">dialect = org.hibernate.dialect.HSQLDialect</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">hbm2ddl.auto = create</span><br />
<br />
<span style="font-family: inherit;"><b>Exception B:</b></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.Query.getResultList(Query.java:146)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.catalyst.courses.entities.HibernateTest.searchCoursesQuery(HibernateTest.java:207)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.catalyst.courses.entities.CourseTest.testNamedQueries(CourseTest.java:444)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at java.lang.reflect.Method.invoke(Method.java:498)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runners.ParentRunner.run(ParentRunner.java:363)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.junit.runner.JUnitCore.run(JUnitCore.java:137)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doQuery(Loader.java:932)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doList(Loader.java:2615)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.doList(Loader.java:2598)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.Loader.list(Loader.java:2425)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2160)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:992)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>... 28 more</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">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)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)</init></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>... 43 more</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: MATCH</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.error.Error.error(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.error.Error.error(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.readColumnOrFunctionExpression(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadSimpleValueExpressionPrimary(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadAllTypesValueExpressionPrimary(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadAllTypesPrimary(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadAllTypesFactor(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadAllTypesTerm(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadAllTypesCommonValueExpression(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadBooleanPrimaryOrNull(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadBooleanTestOrNull(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadBooleanFactorOrNull(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadBooleanTermOrNull(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadBooleanValueExpression(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.readWhereGroupHaving(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadTableExpression(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadQuerySpecification(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadSimpleTable(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadQueryPrimary(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadQueryTerm(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadQueryExpressionBody(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.XreadQueryExpression(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserDQL.compileCursorSpecification(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserCommand.compilePart(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.ParserCommand.compileStatement(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.Session.compileStatement(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.StatementManager.compile(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>at org.hsqldb.Session.execute(Unknown Source)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>... 47 more</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: inherit;"><b>Root Cause B:</b><br />:: 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.</span>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-57832852693941692602017-01-18T15:55:00.000-05:002017-01-18T15:55:31.513-05:00LG Tablet Frozen on Firmware UpdateI'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:<br />
<br />
- battery drained completely, cannot be turned on because battery is at 0%<br />
- plug in the tablet to charge<br />
- screen displays (paraphrasing a bit): Firmware updating, do not unplug.<br />
- screen displays a progress bar under the message and the progress bar never progresses<br />
<br />
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.<br />
<br />
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 <a href="https://community.verizonwireless.com/thread/831680?start=20&tstart=0">this forum</a>, which I will repeat below<br />
<br />
<ol>
<li>Unplug the tablet from the USB cable</li>
<li>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.</li>
<li>Hold down the power button on the tablet for <b>10 seconds</b></li>
<li>While still holding down the power, plug the tablet in and then let go of the power button</li>
<li>You should see the outline of a large battery saying 0% for a second and the screen goes blank</li>
<li>Leave the tablet plugged in to complete charging</li>
</ol>
<div>
Thanks for nothing Microsoft </div>
Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com5tag:blogger.com,1999:blog-2587581514321322199.post-49608957474801764492016-10-07T07:41:00.001-04:002016-10-07T07:41:34.912-04:00GWT 2.7.0 and Java 1.8Well 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?<br />
<br />
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.<br />
<br />
The current warning I get when I compile my GWT module is:<br />
<br />
[INFO] Tracing compile failure path for type 'org.eaglei.ui.gwt.search.SearchApplication'<br />
[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'<br />
[INFO] [ERROR] org.eaglei.ui.gwt.uiconfig.rpc.SearchUIConfigServiceRemoteAsync cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.ui.gwt.search.common.SearchBarWidget cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.ui.gwt.search.SearchApplicationContext cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.services.uiconfig.SearchUIConfig cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.ui.gwt.search.SearchApplicationContext cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.services.uiconfig.SearchUIConfig cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] org.eaglei.common.util.nodeinfo.NodeConfig cannot be resolved to a type<br />
[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'<br />
[INFO] [ERROR] Line 308: Type mismatch: cannot convert from List<capture#3-of ? extends Object> to List<InstitutionConfig><br />
<br />
So what the crap? I tried googling that last bit about List<capture#3- of ? extends Object> 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.<br />
<br />
It turns out it is because of a Java 1.8 enhancement I was using. Instead of:<br />
<br />
List<Thing> thingList = new ArrayList<Thing>();<br />
<br />
You can now omit the second type specifier:<br />
<br />
List<Thing> thingList = new ArrayList<>();<br />
<br />
Fantastic!<br />
<br />
Except if you use it in one of those fancy schmancy one line tertiary statements. In my code, the offending line of code was:<br />
<br />
final List<InstitutionConfig> otherInstitutions = (other.getInstitutions() != null) ? other.getInstitutions() : new ArrayList<>();<br />
<br />
By specifying the type in the tertiary statement, all was good:<br />
<br />
final List<InstitutionConfig> otherInstitutions = (other.getInstitutions() != null) ? other.getInstitutions() : new ArrayList<InstitutionConfig>();<br />
<br />
Yay?Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-12817787504700168992014-02-19T20:43:00.003-05:002014-02-19T20:43:58.208-05:00Getting Apple Mail's Smart Mailboxes to remember Outlook Exchange foldersI'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.<div>
<br /></div>
<div>
For example, I have created a folder named <span style="font-family: Courier New, Courier, monospace;">test</span><span style="font-family: inherit;"> in my Exchange account. I then created a Smart Mailbox named </span><span style="font-family: Courier New, Courier, monospace;">Test Mailbox</span><span style="font-family: inherit;"> to look at this folder:</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-IcE5GLiM2xQ/UwVU56OT6qI/AAAAAAAADtQ/enJahnAcL28/s1600/FirstTry.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-IcE5GLiM2xQ/UwVU56OT6qI/AAAAAAAADtQ/enJahnAcL28/s1600/FirstTry.jpg" height="320" width="315" /></a></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
After I click <span style="font-family: Courier New, Courier, monospace;">OK</span><span style="font-family: inherit;">, and go to edit the Smart Mailbox again:</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-my4IZ7u55wM/UwVVI3eJC6I/AAAAAAAADtY/hTKNEv0cto0/s1600/FirstTry_Fail.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-my4IZ7u55wM/UwVVI3eJC6I/AAAAAAAADtY/hTKNEv0cto0/s1600/FirstTry_Fail.jpg" height="121" width="320" /></a></div>
<div>
<br /></div>
<div>
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.</div>
<div>
<br /></div>
<div>
I initially started down the path of creating a Smart Mailbox with the following filters:</div>
<div>
1) Look for <span style="font-family: Courier New, Courier, monospace;">Messages not in Mailbox</span><span style="font-family: inherit;"> and select </span><span style="font-family: Courier New, Courier, monospace;">Inbox</span></div>
<div>
<span style="font-family: inherit;">2) Build a complex filter that is the same as the rules being applied to move messages to the desired folder</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">It turns out I needed to build some complex filters (combinations of </span><span style="font-family: Courier New, Courier, monospace;">OR</span><span style="font-family: inherit;"> and </span><span style="font-family: Courier New, Courier, monospace;">AND</span><span style="font-family: inherit;">) which the dialog doesn't allow for. The dialog only gives the option of doing one or the other. I stumbled across this <a href="http://static.oyam.ca/archive/ozero/articles/complex_criteria_with_smart_mailboxes.html" target="_blank">post</a> that helped me build some more complicated filters.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
One thing I'd like to point out is that the folder & file name has changed since the <a href="http://static.oyam.ca/archive/ozero/articles/complex_criteria_with_smart_mailboxes.html" target="_blank">post</a>:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">[User]/Library/Mail/V2/MailData/SyncedSmartMailboxes.plist</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">** CAVEAT: Please be sure you back up any of the *.plist files you are going to play with in case things go horribly awry. **</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
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 <span style="font-family: Courier New, Courier, monospace;">Test Mailbox</span> to look in my Exchange folder <span style="font-family: Courier New, Courier, monospace;">test</span><span style="font-family: inherit;"> and then I looked in the file and searched for this Smart Mailbox:</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-0Syi9X2668k/UwVZeQNTuUI/AAAAAAAADtk/3Tq0b8lbZJ8/s1600/WeirdStringForFolder.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-0Syi9X2668k/UwVZeQNTuUI/AAAAAAAADtk/3Tq0b8lbZJ8/s1600/WeirdStringForFolder.jpg" height="46" width="320" /></a></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">And that long garbled string is the problem. For whatever reason, the destination mailbox URL gets completely mangled.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">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:</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">[User]/Library/Mail/V2/MailData/SyncedRules.plist</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
I searched this file for my <span style="font-family: Courier New, Courier, monospace;">Test</span><span style="font-family: inherit;"> folder and found a</span> not garbled URL to my folder:</div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-GnD1AB4eJYA/UwVbhM09GII/AAAAAAAADtw/6inr9afKMCc/s1600/ActualURLForFolder.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-GnD1AB4eJYA/UwVbhM09GII/AAAAAAAADtw/6inr9afKMCc/s1600/ActualURLForFolder.jpg" height="128" width="320" /></a></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
Copy this URL and paste it in place of that garbled string:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-0crfN7hrflM/UwVcR_p5qPI/AAAAAAAADt4/Vn_MH_fkrec/s1600/TaDa.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-0crfN7hrflM/UwVcR_p5qPI/AAAAAAAADt4/Vn_MH_fkrec/s1600/TaDa.jpg" height="70" width="320" /></a></div>
<div>
<br /></div>
<div>
And ta-da! I now have a Smart Mailbox that is looking inside my Exchange folder.</div>
<div>
<br /></div>
<div>
To summarize:</div>
<div>
1) Create a rule that moves emails to the desired folder.</div>
<div>
2) Create a Smart Mailbox, as you normally would, pointing to the desired folder and any other conditions.</div>
<div>
3) Search the <span style="font-family: 'Courier New', Courier, monospace;">[User]/Library/Mail/V2/MailData/SyncedRules.plist</span> file for the desired folder and look for the <span style="font-family: Courier New, Courier, monospace;">CopyToMailboxURL</span><span style="font-family: inherit;"> key.</span></div>
<div>
<span style="font-family: inherit;">4) Copy the URL under the key.</span></div>
<div>
<span style="font-family: inherit;">5) Search the </span><span style="font-family: 'Courier New', Courier, monospace;">[User]/Library/Mail/V2/MailData/SyncedSmartMailboxes.plist</span><span style="font-family: inherit;"> for the new Smart Mailbox.</span></div>
<div>
<span style="font-family: inherit;">6) Paste the URL over the garbled string.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">Enjoy!</span></div>
Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com3tag:blogger.com,1999:blog-2587581514321322199.post-75083810631590090182013-12-26T23:48:00.001-05:002013-12-26T23:48:29.016-05:00Xbox One & WPA2 routerToday'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. <br />
<br />
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 ..<br />
<br />
The solution? Don't use the auto discovery.<br />
<br />
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.<br />
<br />
Happy holidays everyone!Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-4452778252108502872013-12-10T18:57:00.001-05:002013-12-10T23:31:45.193-05:00Getting eclipse to co-operate with maven & subversionOh 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.<br />
<div>
<br /></div>
<div>
Today's frustration has been brought to you by maven, subversion and eclipse.<br />
<br />
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.<br />
<br />
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.<br />
<br />
So, to help myself (as well as anyone else floundering) avoid painful eclipse updates, here are the steps for the following configuration:<br />
<br />
<ul>
<li>Local (my machine):</li>
<ul>
<li>Eclipse Kepler Release 1 - Java EE</li>
<li>Mac OSX Mountain Lion (10.8.5)</li>
</ul>
<li>Server (somewhere in the wild wild web):</li>
<ul>
<li>Maven 3.0.5</li>
<li>Subversion 1.6.11</li>
</ul>
</ul>
<div>
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.</div>
<div>
<br /></div>
<div>
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.<br />
<br /></div>
<div>
Without further ado, here we go.</div>
<div>
<ol>
<li>Start Eclipse</li>
<li>Help -> Eclipse Marketplace ...</li>
<li>Install Maven Integration</li>
<ul>
<li><i>~ EDIT ~</i></li>
<ul>
<li><i>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.</i></li>
</ul>
<li>Type in 'Maven Integration' in the search box</li>
<li>Scroll down until you find:</li>
<ul>
<li>Maven Integration for Eclipse (Juno and Newer) 1.4</li>
<li>eclipse.org, epl</li>
</ul>
<li>Click 'Install'.</li>
<li><b>Do not finish the install yet</b></li>
<li>Click '< Install More'</li>
</ul>
<li>Install a Subversion solution (NB: There are two options, both are listed)</li>
<ul>
<li>Type in 'Subversion' in the search box</li>
<li><i>Option 1</i>: Subversive</li>
<ul>
<li>Scroll down until you find:</li>
<ul>
<li>Subversive - SVN Provider 1.1.1</li>
<li>eclipse.org, epl</li>
</ul>
<li>Click 'Install Now'</li>
<li>Break (Go to step 5)</li>
</ul>
<li><i>Option 2</i>: Subclipse</li>
<ul>
<li><i>~ EDIT ~</i></li>
<ul>
<li><i>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.</i></li>
</ul>
<li>Exit the Eclipse Marketplace</li>
<li>Install the solution directly:</li>
<ul>
<li>Help -> Install New Software</li>
<li>Add a new software style:</li>
<ul>
<li>http://subclipse.tigris.org/update_1.8.x/</li>
</ul>
</ul>
<li>Go to step 7.</li>
<li><strike>Scroll down until you find:</strike></li>
<ul>
<li><strike>Subclipse 1.8.22</strike></li>
<li><strike>Subclipse Project, epl</strike></li>
</ul>
<li><strike>Click 'Install Now'</strike></li>
<li><strike>Break (Go to step 5)</strike></li>
</ul>
</ul>
<li>You will now see screen with a list of all of the items that will be installed for the selected solutions. <b> </b></li>
<li>If you are using <i style="font-weight: bold;">Option 1: Subversive</i>, there are no additional steps. All the features should be selected for the two solutions.</li>
<li>If you are using <i style="font-weight: bold;">Option 2: Subclipse</i>, you will need to perform an additional step to avoid future headaches.</li>
</ol>
<b></b><br />
<div style="text-align: center;">
<b><b><img border="0" height="165" src="http://1.bp.blogspot.com/-n7glbROZsWc/UqefR9Sa1AI/AAAAAAAAC9Y/7Ujsw4fzBXI/s320/Step_6.jpg" width="320" /></b></b></div>
<br />
<ol><ul>
<li>Expand the Subclipse folder</li>
<ul>
<li><b>Uncheck</b> 'Subversion JavaHL Native Library Adapter'</li>
</ul>
<li>Expand the SCNKit folder</li>
<ul>
<li>Ensure that 'SVNKit Client Adapter' is <b>checked</b></li>
</ul>
</ul>
</ol>
<ol start="8">
<li>You will now be prompted to restart eclipse, restart eclipse.</li>
</ol>
<b></b><br />
<div class="separator" style="clear: both; text-align: center;">
<b><a href="http://3.bp.blogspot.com/-QSdgPwiQExs/UqejgaKPdtI/AAAAAAAAC9s/Mxl8XhSjSwg/s1600/Step_9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="46" src="http://3.bp.blogspot.com/-QSdgPwiQExs/UqejgaKPdtI/AAAAAAAAC9s/Mxl8XhSjSwg/s320/Step_9.jpg" width="320" /></a></b></div>
<br />
<ol start="9">
<li>Welcome back! Switch to the 'Java' perspective. </li>
<ul>
<li>If you don't have the 'Java' perspective as an option, do this:</li>
<ul>
<li>Window -> Open Perspective -> Other... -> Java</li>
</ul>
</ul>
</ol>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-j-9uKqp9hFY/UqekDenujAI/AAAAAAAAC90/Z1RPhvp3ta0/s1600/Step_10.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-j-9uKqp9hFY/UqekDenujAI/AAAAAAAAC90/Z1RPhvp3ta0/s320/Step_10.jpg" width="316" /></a></div>
<div>
<br /></div>
<ol start="10">
<li>Select the 'Package Explorer' view.</li>
<ul>
<li>If you don't have the 'Package Explorer' view, do this:</li>
<ul>
<li>Window -> Show View -> Other... -> Package Explorer</li>
</ul>
</ul>
<li>Right click in the empty area and select 'Import'</li>
<li>Filter the import source for 'Maven'</li>
<ul>
<li>Select 'Check out Maven Projects from SCM'</li>
<li>Click 'Next >'</li>
</ul>
</ol>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-NkEuSJk7vZ0/Uqekek1QFFI/AAAAAAAAC-E/8Bg2YPCI7FY/s1600/Step_13.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-NkEuSJk7vZ0/Uqekek1QFFI/AAAAAAAAC-E/8Bg2YPCI7FY/s320/Step_13.jpg" width="303" /></a></div>
<div>
<br /></div>
<ol start="13">
<li>Select the m2e Marketplace link</li>
<ul>
<li>NB: This is not the same marketplace as the eclipse marketplace</li>
</ul>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-uSajhS2FbNw/UqenRlSrPpI/AAAAAAAAC-Q/R8_AZm3seBE/s1600/Step_14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="227" src="http://1.bp.blogspot.com/-uSajhS2FbNw/UqenRlSrPpI/AAAAAAAAC-Q/R8_AZm3seBE/s320/Step_14.jpg" width="320" /></a></div>
<div>
<br /></div>
<ol start="14">
<li>Scroll down until you see the section 'm2e Team providers'.</li>
<ul>
<li>If you are using <i>Option 1: Subversive</i> (from step 4), select the option that has been highlighted in blue.</li>
<ul>
<li>m2e-subversive</li>
</ul>
<li>If you are using <i>Option 2: Subclipse</i> (from step 4), select the option that has been highlighted in pink.</li>
<ul>
<li>m2e-subclipse</li>
</ul>
</ul>
<li>Click 'Finish' and follow the prompts to complete installation. You will be prompted to restart eclipse again, so restart eclipse.</li>
<li>C'est Fin!</li>
</ol>
<div>
You should now be able to check out maven projects from your svn repository. Enjoy!</div>
<br />
<ol><ul></ul>
</ol>
</div>
</div>
Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-88755528446703074652012-11-15T17:05:00.001-05:002012-11-15T17:05:26.696-05:00Debugging GWT using eclipse and tomcatEverything I've heard and read online indicated that setting up my eclipse to debug the client side portions of a GWT app is super easy ... so of course I end up flailing around helplessly into the wee hours trying to debug a supposedly simple client side bug. My process up to this point has been to insert a crazy amount of ridiculous log statements into the code, compile, deploy, repeat. I know that this is messy and sloppy, but I was adamantly against using the GWT debugger because of a prior attempt to get it going a year and half ago that turned into a huge time-suck and frustrations. After having spent an exceedingly long night trying to debug something a few months ago that ended up taking as long as it did because of the multiple repetitions of inserting log statements, compile, deploy, repeat, I conceded that I had to get the GWT debugger working.<br />
<br />
First off, I am deploying the application in a local tomcat, so I need to be able to debug what eclipse considers an external server ( as opposed to having eclipse / gwt spin up a server within eclipse ). A quick <a href="http://lmgtfy.com/?q=gwt+debug+eclipse+external+server" target="_blank">google search</a> for the keywords of interest brings up as the first result a very helpful <a href="http://stackoverflow.com/a/4857661" target="_blank">stackoverflow answer</a>:<br />
<br />
<br />
<ol style="background-color: white; border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1em 30px; padding: 0px; vertical-align: baseline;">
<li style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; word-wrap: break-word;">Get <a href="http://code.google.com/eclipse/" rel="nofollow" style="background-color: transparent; border: 0px; color: #4a6b82; cursor: pointer; margin: 0px; padding: 0px; text-decoration: initial; vertical-align: baseline;">google plugin for eclipse</a></li>
<li style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; word-wrap: break-word;">The in eclipse, right click on your project and choose <strong style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">Debug as -> Web Application (running on external server)</strong></li>
<li style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; word-wrap: break-word;">Enter URL of your web app on tomcat (like <a href="http://localhost:8080/YourApp/YourApp.html" rel="nofollow" style="background-color: transparent; border: 0px; color: #4a6b82; cursor: pointer; margin: 0px; padding: 0px; text-decoration: initial; vertical-align: baseline;">http://localhost:8080/YourApp/YourApp.html</a> and eclipse will give you new one - it will add stuff like ?gwt.codesvr=127.0.0.1:9997</li>
</ol>
<br />
Simple, right? Sadly step 2 did nothing for me. I select it, and nothing happens. So what I ended up doing was to set up my own debug configurations. When I did this, I kept getting this annoying error:<br />
<br />
<br />
<div class="p1">
<span style="color: red;">Working directory does not exist: /Users/myStuff/Documents/workspace/myProject-TRUNK/webapp/helloWorld/target/helloWorld-webapp-1.7-MS2.01-SNAPSHOT</span></div>
<br />
<br />
I thought that perhaps this may have been related to the fact that we use maven and maybe that was throwing another complication into the mix. As it turns out, if you don't provide a location of the deployed war to the configurations, GWT tries to access what it thinks the location. The directory does in fact not exist, nor is it where my deployed war lives. After some random clicking around and setting the directory to different places that may make sense, I figured out what it was looking for. So, in summary, this is another way to get the GWT debugger to work by manually configuring things:<br />
<br />
<ol>
<li><span style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;">In eclipse, right click on your project and choose</span><span style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;"> </span><strong style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;">Debug as -> Debug Configurations ...</strong></li>
<li><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;">In the left hand panel, scroll down to "Web Application", select it and then click new.</span><div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-uVCqIzOVNfg/UKVfp182JSI/AAAAAAAABLg/XyHsAMVLvsY/s1600/debug-configurations.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-uVCqIzOVNfg/UKVfp182JSI/AAAAAAAABLg/XyHsAMVLvsY/s1600/debug-configurations.jpg" height="176" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
</li>
<li><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;">Click on the New_configuration to edit it</span></li>
<li><span style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;">In the </span><span style="font-family: Courier New, Courier, monospace; font-size: 14px; line-height: 18px;">Main</span><span style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;"> tab, change the name of the configuration to something meaningful to you so you know what this configuration is for. The project should be pre-filled with the name of the GWT app that you right clicked over. If it isn't, or it is not correct, click on the browse button to select the project. This was a slight point of confusion for me, what project should I use? The code base I work on is very large with many modules. I chose the entry point into the application for the client as the GWT project ( and I chose correctly it seems ). I didn't know what main class to use or read up on what my options were, so I just left the default value.</span><div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-dlqHHj3ibR0/UKViADmGOkI/AAAAAAAABLo/gmL3ykiispU/s1600/debug-configurations-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-dlqHHj3ibR0/UKViADmGOkI/AAAAAAAABLo/gmL3ykiispU/s1600/debug-configurations-2.jpg" height="222" width="320" /></a></div>
</li>
<li><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;">Now go to the </span><span style="border: 0px; font-family: Courier New, Courier, monospace; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;">Server</span><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;"> tab. Because I am running tomcat locally on my machine, I do <b>not</b> want to use the embedded server, so uncheck this option. </span><div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-PRmJ3O9iGaY/UKViz_aVdeI/AAAAAAAABLw/54FoQ20WM2g/s1600/debug-configurations-3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-PRmJ3O9iGaY/UKViz_aVdeI/AAAAAAAABLw/54FoQ20WM2g/s1600/debug-configurations-3.jpg" height="222" width="320" /></a></div>
</li>
<li><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;">Now go to the </span><span style="border: 0px; font-family: Courier New, Courier, monospace; margin: 0px; padding: 0px; vertical-align: baseline;">GWT</span><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;"> tab. Type in the name of the URL you would use in a browser to access your application. If you don't see the URL field, you probably forgot to uncheck the use embedded server in the previous step. In my case, my application is running on https and the url needs to reflect this. Additionally, note that the class that has your entry point should show up here.</span> </span><div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-yIlSLHvoMWI/UKVlo_plIRI/AAAAAAAABME/LEwbvt2e3sk/s1600/debug-configurations-5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-yIlSLHvoMWI/UKVlo_plIRI/AAAAAAAABME/LEwbvt2e3sk/s1600/debug-configurations-5.jpg" height="222" width="320" /></a></div>
</li>
<li><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;">Now go to the </span><span style="border: 0px; font-family: Courier New, Courier, monospace; margin: 0px; padding: 0px; vertical-align: baseline;">Arguments</span><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;"> tab. Here's where I ended up flailing for a bit. At the beginning of the program arguments, add the following:</span></span></span><div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Courier New, Courier, monospace;">-war /opt/tomcat6/webapps/helloWorld/ </span></div>
You should use the fully qualified path to the your deployed application folder (not the *.war file)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-z1n5MUCijwk/UKVmKy2ndkI/AAAAAAAABMM/A-00lpN_FX0/s1600/debug-configurations-6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-z1n5MUCijwk/UKVmKy2ndkI/AAAAAAAABMM/A-00lpN_FX0/s1600/debug-configurations-6.jpg" height="222" width="320" /></a></div>
</li>
<li><span style="border: 0px; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;">Finally, you should probably add all the source for your project if you want to step through the debugger to the </span><span style="border: 0px; font-family: Courier New, Courier, monospace; margin: 0px; padding: 0px; vertical-align: baseline;">Source</span><span style="border: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; margin: 0px; padding: 0px; vertical-align: baseline;"> tab.
</span></span></span></li>
</ol>
<div>
<span style="font-family: Arial, Liberation Sans, DejaVu Sans, sans-serif;"><span style="font-size: 14px; line-height: 18px;">And that's it! When you click on debug, you should see a tab on your screen where your console is that says "Development Mode". One other probably obvious thing is that you want to start up tomcat first before clicking debug. After this, you'll see in the Development Mode console a URL you can copy and paste into a browser and use for debugging the client side.</span></span></div>
<div>
<span style="font-family: Arial, Liberation Sans, DejaVu Sans, sans-serif;"><span style="font-size: 14px; line-height: 18px;"><br /></span></span></div>
<div>
<span style="font-family: Arial, Liberation Sans, DejaVu Sans, sans-serif;"><span style="font-size: 14px; line-height: 18px;">Yes, I know, this should be simple and straight forward, but I figured if I was having trouble ... I'm sure (hopefully) someone out there on the interwebs is having similar troubles.</span></span></div>
Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com1tag:blogger.com,1999:blog-2587581514321322199.post-4175639270253015732012-03-20T13:23:00.002-04:002012-03-20T13:23:34.672-04:00The quest for the upgrade continues ...After my last post, I was confident that things would go smoothly, having assumed that those were the most deceptive issues I would encounter. Sadly, that was not at all the case. Upon doing a <span style="font-family: 'Courier New', Courier, monospace;">mvn install</span> on the command line, I got this error:<br />
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 1)</span></div>
<pre class="brush:bash">|Loading Grails 2.0.1
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.298s
[INFO] Finished at: Sat Mar 17 19:22:13 EDT 2012
[INFO] Final Memory: 20M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.grails:grails-maven-plugin:2.0.1:exec (default-cli) on project caffiendFrog-webapp-service: Unable to start Grails: java.lang.reflect.InvocationTargetException: Provider for javax.xml.parsers.SAXParserFactory cannot be found -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
</pre>
<br />
A quick google search for the error, in various combinations of keywords, didn't produce anything that helped. I turned to the footnote in the error, which suggests an <a href="http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException" target="_blank">article</a> that may help. It basically says that there is something wrong with your <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> file, specifically some configuration is done correctly or something else is wrong. It's a rather general article, but it did help in that I was able to focus my efforts digging through my <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span>.<br />
<br />
Here are some red-herrings (i.e. false leads) that I tried:<br />
<br />
<ul>
<li>The message mentions something about my <span style="font-family: 'Courier New', Courier, monospace;">grails-maven-plugin</span>, so I spent a lot of time commenting out various bits of it. </li>
<li>Tried a <span style="font-family: 'Courier New', Courier, monospace;">mvn clean install</span> and got a similar message, only instead of <span style="font-family: 'Courier New', Courier, monospace;">(default-cli)</span>, I got <span style="font-family: 'Courier New', Courier, monospace;">(default clean)</span>.</li>
<li>And many more combinations of commenting things and searching for the plugin's information online to see if my configurations were incorrect.</li>
</ul>
<div>
As a last ditch effort, I created 2 dummy test applications, using the <a href="http://grails.org/doc/latest/guide/commandLine.html#4.5 Ant and Maven" target="_blank">grails instructions</a> for creating a maven-ized project, to take a look at their <span style="font-family: 'Courier New', Courier, monospace;">poms</span>. Up until now, I had assumed that most of the stuff in my <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> was stuff we had intentionally put in there (keep in mind as I said, it's been awhile and I can't remember what we added and what grails put in for us). So I created a blank project using Grails version 1.3.7 and a blank project using Grails 2.0.1. And lo and behold ... the poms are very different indeed:</div>
<div>
<ul>
<li><a href="https://sites.google.com/site/caffiendfrog/ribbit/grails/pom_137.xml?attredirects=0&d=1" target="_blank">Grails 1.3.7 (pom.xml)</a></li>
<li><a href="https://sites.google.com/site/caffiendfrog/ribbit/grails/pom_201.xml?attredirects=0&d=1" target="_blank">Grails 2.0.1 (pom.xml)</a></li>
</ul>
Given the vast difference, what I did next was:</div>
<div>
<ol>
<li>Compare our original (v1.3.7) <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> to the generated one above.</li>
<li>Noted the differences between them, these difference would be items that we had put in.</li>
<ul>
<li>i.e. We added an additional exclusion to the dependencies from org.grails:</li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 2)</span></div>
<pre class="brush:xml"><exclusion>
<artifactid>jcl-over-slf4j</artifactid>
<groupid>org.slf4j</groupid>
</exclusion> </pre>
<li>i.e.We had an additional dependency in our original file:</li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 3)</span></div>
<pre class="brush:xml"><dependency>
<groupid>org.slf4j</groupid>
<artifactid>jcl-over-slf4j</artifactid>
<version>${slf4j-version}</version>
</dependency>
</pre>
<li>i.e. We had a "hack" in place to synchronize the app.version in Grail's application.properties file with the version in our POM. See <a href="http://jira.grails.org/browse/MAVEN-79">MAVEN-79</a> and <a href="http://jira.grails.org/browse/MAVEN-128">MAVEN-128</a>, as well as an additional execution in our configuration of the grails-maven-plugin: </li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 4)</span></div>
<pre class="brush:xml"><plugin>
<groupid>org.grails</groupid>
<artifactid>grails-maven-plugin</artifactid>
<version>${grails-version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>sync-versions</id>
<phase>validate</phase>
<goals>
<goal>set-version</goal>
</goals>
</execution>
<execution>
<id>grails-clean</id>
<phase>clean</phase>
<goals>
<goal>set-version</goal>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin> </pre>
</ul>
<li>Changed the <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> to look like the v2.0.1 (i.e. the dependencies, plugins, repos, etc.)</li>
<li>Inserted the differences into the new <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span>.</li>
<ul>
<li>i.e. Inserting the additional exclusion from <span style="font-family: 'Courier New', Courier, monospace;">Listing 2</span><span style="font-family: Times, 'Times New Roman', serif;">, note that in the v2.0.1 </span><span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span><span style="font-family: Times, 'Times New Roman', serif;">, there is only one dependency to org.grails and it contains none of the exclusions that were listed in v1.3.7:</span></li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 2a)</span></div>
<pre class="brush:xml"><dependency>
<groupid>org.grails</groupid>
<artifactid>grails-dependencies</artifactid>
<version>${grails-version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactid>jcl-over-slf4j</artifactid>
<groupid>org.slf4j</groupid>
</exclusion>
</exclusions>
</dependency>
</pre>
<li> i.e. Added in our additional dependency:</li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 3a)</span></div>
<pre class="brush:xml"><dependency>
<groupid>org.slf4j</groupid>
<artifactid>jcl-over-slf4j</artifactid>
<version>${slf4j-version}</version>
</dependency>
</pre>
<li>i.e. Upon further investigation, the tickets have been resolved and the hack is no longer needed. Inserted the additional execution into our new plugin definition:</li>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(Listing 4a)</span></div>
<pre class="brush:xml"><plugin>
<groupid>org.grails</groupid>
<artifactid>grails-maven-plugin</artifactid>
<version>${grails-version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>grails-clean</id>
<phase>clean</phase>
<goals>
<goal>set-version</goal>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</pre>
</ul>
</ol>
You get the idea. <br />
<br />
Some other things to note:<br />
<br />
<ul>
<li>The plugin JAXRS & Hibernate have a dependencies on org.restlet*. This is no longer available via maven central. You will need to add:<br />
</li>
</ul>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace;">mavenRepo "http://maven.restlet.org"</span></div>
<ul>To your <span style="font-family: 'Courier New', Courier, monospace;">BuildConfig.groovy</span> file and/or your <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> file as an external repository.</ul>
<ul>
<li>I initially had trouble getting the archetype for v2.0.1. For some reason the command <span style="font-family: 'Courier New', Courier, monospace;">mvn archetype:generate</span> just would not pick up the new version, even though it is there and available. To resolve this, I trashed my <span style="font-family: 'Courier New', Courier, monospace;">.m2</span> folder and when the dependencies were pulled in, it pulled in the new version of the archetype.</li>
</ul>
As always, I think there were some issues I ran across, but at the moment I can't think of them. Also, at this point, the upgrade still isn't complete, and I'm getting errors, but at least the errors seem to be related to the code and possible re-naming and re-factoring that occurred in the new version.<ul>
</ul>
</div>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com1tag:blogger.com,1999:blog-2587581514321322199.post-47054569172869676982012-03-17T20:10:00.003-04:002012-03-17T20:35:49.580-04:00Oh un-holy grails ...It has been a while... which isn't to say I haven't been running to a myriad of issues, but I just haven't had the time to update. But this one, egads. I could not help but describe and hopefully save someone out there in the interwebs many hours and tears.<br />
<br />
Our adventure today begins with a seemingly simple task. Upgrading the Grails version for a project. The project was previously on Grails 1.3.7, and we are upgrading/updating/whichever it to 2.0. For a point of reference, here is the setup/environment :<br />
<ul>
<li>This a fairly large code base containing many other modules. </li>
<li>We are using maven</li>
<li>My IDE of choice is Eclipse Helios (64bit)</li>
<li>We have a 'local' nexus that proxies stuff for us</li>
</ul>
In addition to the base Grails, we have the following plugins installed:<br />
<ul>
<li>Spring-Security-Core</li>
<li>Spring-Security-Ui</li>
<ul>
<li>Mail</li>
<li>JQuery</li>
<li>JQuery-ui</li>
<li>famfamfam</li>
</ul>
<li>tomcat</li>
<li>hibernate</li>
<li>jaxrs</li>
</ul>
And we also have the following dependencies:<br />
<ul>
<li>Spring-Security-Core </li>
<li>Spring-Security-Web</li>
</ul>
Note that there are two separate Spring-Security-Core, one is a plugin and one is a dependency to be added in the pom.xml. Another note, it has been many months since we set up our Grails project, and my memory just isn't what it used to be.<br />
<br />
Here's an overview of what this blog entails:<br />
<ul>
<li>Where are the jars?</li>
<li>Multiple versions of grails in the same workspace</li>
<li>Wait, I need to INSTALL grails as well??</li>
<li>Grails "upgrade" command doesn't work with maven-ized projects</li>
<li>Trouble re-installing the JAXRS plugin</li>
<li>Some final thoughts</li>
</ul>
<b><i><u><span style="font-size: large;">Issue #1 - Where are the jars?</span></u></i></b><br />
My first problem will probably be moot for most people now. I could not get the updated jars from our local nexus. It took a little searching and I came across this: <a href="http://jira.grails.org/browse/GRAILS-8710?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab#issue-tabs" target="_blank">Grail 2.0 jars not available through maven central</a>. Which of course explains why our nexus didn't pull it in. The reason this is moot now is that Grails 2.0<b>.1</b> <i>is</i> available through maven central. So I was able to grab the jars for 2.0.1 fine. But for future reference, if you experience trouble pulling in the jars for new versions of Grails ... check to see if they even exist in your nexus or maven central. If not, you can grab them from Grails' repo: <a href="http://repo.grails.org/grails/core" target="_blank">http://repo.grails.org/grails/core</a>.<br />
<br />
<b><i><u><span style="font-size: large;">Issue #2 - Multiple versions of grails in the same workspace.</span></u></i></b><br />
Since this is a major release of Grails, there are many things that have been changed and therefore our code needs to be changed to work with the Grails. Grails does provide a nice* write-up of how to upgrade your code here: <a href="http://grails.org/doc/latest/guide/gettingStarted.html#upgradingFromPreviousVersionsOfGrails" target="_blank">Upgrading From Previous Versions of Grails</a>. <br />
<br />
*Since I have only just resolved my issues with getting started, I haven't yet had a chance to follow their write-up, but at a glance, it looks fairly detailed. Whether or not it is detailed enough, I will find out soon.<br />
<br />
Because this is potentially going to perturb our code base with all the changes, I am working the upgrade in a branch that contains only this module. Seems like a sound plan, right? At this moment, I have our entire code base open in eclipse and I have this branch open. As soon as I change the POM to reference 2.0.1, and eclipse does its auto build thing to pick up this change ... the bad thing happens. Namely, eclipse exits all by it's lonesome, with no message or anything. Just, one minute it's building ... next minute it's gone. <br />
<br />
What happened? Since I'm on a Mac, I opened up the console to take a look at what it says.. and it says a lot:<br />
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 1)</span></div>
<pre class="brush:bash">ar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: /Users/frog/Documents/workspaceNew/caffiendFrog-webapp-service-BRANCH/plugins/spring-security-core-1.2.7.2/src/java/grails/plugins/springsecurity/DigestAuthPasswordEncoder.java:88: cannot find symbol
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: symbol : variable Hex
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: location: class grails.plugins.springsecurity.DigestAuthPasswordEncoder
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: return new String(Hex.encode(digest.digest(s.getBytes())));
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: ^
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: /Users/frog/Documents/workspaceNew/caffiendFrog-webapp-service-BRANCH/plugins/spring-security-core-1.2.7.2/src/java/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.java:179: cannot find symbol
.... (Lots more errors along the same lines, cannot find symbols) ...
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: 100 errors
Mar 16 11:31:16 dhc019746 [0x0-0x1f51f5].org.eclipse.eclipse[5701]: 1 error
Mar 16 11:31:16 dhc019746 com.apple.launchd.peruser.503[184] ([0x0-0x1f51f5].org.eclipse.eclipse[5701]): Exited with exit code: 1
</pre>
It took me quite a lot of frustration, many hours, to realize that the problem was that <i>because</i> the two versions of grails is so different, they can not coexist happily, at least not without some tweaking. There is a nice little script available <a href="https://github.com/deluan/grails.sh/blob/master/README.md" target="_blank">here</a> that does the switching automagically based on what version of grails your project needs. You only need to a little bit of setup, namely setting an environment variable to point to a default version of grails, and to have both versions of grails in the same folder. For example, this is what I did:<br />
<br />
<ol>
<li>I decided to use 1.3.7 as my default, so I set my $GRAILS_HOME to point to that in my <span style="font-family: 'Courier New', Courier, monospace;">~/.bashrc</span> file:</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 2)</span></div>
<pre class="brush:bash">export GRAILS_HOME=/opt/grails-1.3.7</pre>
</li>
</ul>
<li> I unzipped and placed both versions under <span style="font-family: 'Courier New', Courier, monospace;">/opt</span>:</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 3)</span></div>
<pre class="brush:bash">frog@hostname:/opt$ ls
total 16
drwxr-xr-x 14 frog staff 476 Mar 16 14:37 .
drwxrwxr-t 37 root admin 1326 Mar 16 14:20 ..
drwxr-xr-x 20 frog admin 680 Nov 2 15:40 grails-1.3.7
drwxr-xr-x@ 21 frog staff 714 Feb 14 16:22 grails-2.0.1
drwx------@ 8 frog staff 272 Mar 16 14:37 grails-docs-1.3.7
drwx------@ 16 frog staff 544 Mar 16 14:36 grails-docs-2.0.1
drwxr-xr-x 3 frog staff 102 Mar 16 14:27 multi-grails
</pre>
</li>
</ul>
<li>I put the script in it's own folder (multi-grails) in the same folder with the grails version and added that information to the $PATH environment variable in the ~/.bashrc file:</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 4)</span></div>
<pre class="brush:bash">export PATH=/opt/multi-grails/:$PATH</pre>
</li>
</ul>
</ol>
<ol></ol>
Maybe this is obvious to more experienced developers, but I've never had this problem before and I know I've worked with multiple versions of libraries opened in the same workspace before. Well, as it turns out ... this is because of my next issue.<br />
<br />
<b><i><u><span style="font-size: large;">Issue #2a - Wait, I need to INSTALL grails as well??</span></u></i></b><br />
This is a painful thing for me to admit, and maybe it's obvious in the documentation on grails and I was just trying to do things too quickly and didn't notice. But I <i>completely</i> forgot I had installed grails on my machine. I just assumed it was a plugin like any other. No, no, no. You need to install grails. And by install grails, I mean:<br />
<ol>
<li>Download the binary zip of the version you want (http://grails.org/Download)</li>
<li>Unzip.</li>
<li>C'est Fin.</li>
</ol>
Face, palm, anyone?<br />
<ol></ol>
<div>
<b><i><u><span style="font-size: large;">Issue #3 - Grails "upgrade" command doesn't work with maven-ized projects</span></u></i></b></div>
<div>
Alright, now that I can actually VIEW my code in eclipse, I can start the upgrading process. Grails provides a nice "upgrade" command to make life easier. It is simply "upgrade". To use this command on the command line with the mavenized grails commands:</div>
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 5)</span></div>
<pre class="brush:bash">mvn grails:exec -Dcommand=upgrade</pre>
Simple, right? Ah, but no. Again, that would be too easy. What you end up with if you try this on the command line is something along the lines of, after lots of downloading of whatever other dependencies your project has:<br />
<div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 6)</span></div>
<pre class="brush:bash">NOTE: Your application currently expects grails version [2.0.1], this target will upgrade it to Grails 1.3.7 ...
WARNING: This target will upgrade an older Grails application to 1.3.7.
Are you sure you want to continue?
(y, n)
y
[delete] Deleting directory /Users/frog/Documents/workspaceNew/blog/target/classes
[delete] Deleting directory /Users/frog/Documents/workspaceNew/blog/target/resources
[delete] Deleting directory /Users/frog/Documents/workspaceNew/blog/target/test-classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:29.344s
[INFO] Finished at: Sat Mar 17 19:25:48 EDT 2012
[INFO] Final Memory: 32M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.grails:grails-maven-plugin:1.3.7:exec (default-cli) on project caffiendFrog-webapp-service: Unable to start Grails: java.lang.reflect.InvocationTargetException: : /Users/frog/Documents/workspaceNew/blog/null/src/war not found. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException</pre>
<br />
If you look at the end of line 17 above, you can see it is looking for: <span style="font-family: 'Courier New', Courier, monospace;">/blah/blah/<b>null</b>/src/war</span>. What the heck, why is it looking for null, and where did that even get specified? According to this <a href="http://davidadawson.wordpress.com/2010/10/20/manual-maven-grails-update/" target="_blank">blog</a>, there is some problem with resolving the environment path and maven and grails. Long story short, it doesn't work. You can't (at this time at least) use the upgrade grails command on a maven-ized project.<br />
<br />
So now what? Now you do the upgrade manually. The above mentioned <a href="http://davidadawson.wordpress.com/2010/10/20/manual-maven-grails-update/" target="_blank">blog</a> entry has instructions as well. Here is what I did, in a little bit more detail. Note that some of the steps I'm not sure are 100% necessary, but I was getting tired of eclipse choking on me.<br />
<br />
<ol>
<li>Exit eclipse.</li>
<li>Navigate to the directory of your project</li>
<li>Using your favorite text editor, manually edit the <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> file to change the grails version to 2.0.1. Note that in our case, we have declared a property at the top of the <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> that is used in all the grails related dependencies for consistency.</li>
<li>Using your favorite text editor, manually edit the <span style="font-family: 'Courier New', Courier, monospace;">application.properties</span> to change the <span style="font-family: 'Courier New', Courier, monospace;">app.grails.version</span> to 2.0.1.</li>
<li>Make a note of all the plugins that are listed in the <span style="font-family: 'Courier New', Courier, monospace;">application.properties</span> file. For example, here are the plugins that our module uses:</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 7)</span></div>
<pre class="brush:bash">plugins.famfamfam=1.0.1
plugins.hibernate=2.0.1
plugins.jaxrs=0.6
plugins.jquery=1.7.1
plugins.jquery-ui=1.8.15
plugins.mail=1.0
plugins.spring-security-core=1.2.7.2
plugins.spring-security-ui=0.2
</pre>
</li>
As I mentioned earlier, it has been a while since we first set this up, so I didn't even remember all the plugins we were using. </ul>
<li>Using the command line, uninstall each of these plugins. The name of the plugin to pass in for the command is what appears after the '.' in your list.</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 8)</span></div>
<pre class="brush:bash">mvn grails:exec -Dcommand="uninstall-plugin" -Dargs="famfamfam"</pre>
</li>
</ul>
<li>Now, install the very same plugins, this time the install will pull in the updated versions of your plugins.</li>
<ul>
<li><div style="text-align: center;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 9)</span></div>
<pre class="brush:bash">mvn grails:exec -Dcommand="uninstall-plugin" -Dargs="famfamfam"</pre>
</li>
</ul>
</ol>
<b><u><i><span style="font-size: large;">Issue #4 - Trouble re-installing the JAXRS plugin</span></i></u></b><br />
One of the plugins that we use is jaxrs ...which has a dependency on some restlet.org packages. For some odd reason, when trying to re-install the plugin, I keep getting errors about inability to resolve the dependency. As it turns out, the restlet version that is needed by the plugin is <b>NOT</b> in maven central. To fix this, I added a repository to the <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: small;">(Listing 10)</span><br />
<pre class="brush:bash"><repository>
<id>restlet.org</id>
<name>restlet.org</name>
<url>http://maven.restlet.org</url>
</repository> </pre>
<b><u><i><span style="font-size: large;">Some final thoughts ... for now...</span></i></u></b><br />
At this point, you should be able to do a <span style="font-family: 'Courier New', Courier, monospace;">mvn clean install</span> on your command line for the project and open both projects up in Eclipse without eclipse having a heart attack and falling over. Keep in mind that your <span style="font-family: 'Courier New', Courier, monospace;">mvn clean install</span> <b>will</b> fail, since you haven't yet changed your code to adhere to the new 2.0.1 ways. This is far as I was able to get to:<br />
<br />
<pre class="brush:bash">[ERROR] Failed to execute goal org.grails:grails-maven-plugin:2.0.1:clean (default-clean) on project eagle-i-webapp-identity-service: Unable to start Grails: java.lang.reflect.InvocationTargetException: Provider for javax.xml.parsers.SAXParserFactory cannot be found -> [Help 1]
</pre>
<br />
Another thing to mention is be wary of messing around with your maven-ized <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> file. If I remember correctly, you had to issue a specific command to turn the grails project into a maven-ized one and that the command also created/edited the <span style="font-family: 'Courier New', Courier, monospace;">pom.xml</span> file. One of the motivating factors for us to upgrade is that we have been seeing our CI builds hang for no explicit reason when building this specific project.. Where it hangs varies, but it seems to be hanging while trying to resolve dependencies (another long story, maybe for another time). I tried to do some "cleverness" by cleaning up what I thought were now obsolete/unused dependencies ... which I should have known better than to do.<br />
<br />
I hope this has been helpful for someone out there. I tried to document this as best as I could, but it was a long, frustrating process. I may have missed some steps, if I did and it's causing you issues, please let me know and I'll try to help out.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com3tag:blogger.com,1999:blog-2587581514321322199.post-7316706927380816492011-11-12T14:50:00.001-05:002011-11-12T14:50:48.890-05:00MacOs Snow Leopard and the disappearing pinyin candidate windowThis post doesn't have very much to do with programming, but it did take me forever to figure this out, so maybe this will help out others who have had this problem.<br />
<br />
I occasionally need to use the Pinyin-simplified on MacOsX Snow Leopard to type Chinese. I'm still fairly new to using Macs... so I've found myself accidentally pressing combinations of keys that I am used to on the Windows, that unfortunately map to entirely different things on the Mac. (I know, bad fingers ... bad). Most recently, I was in the middle of writing up a presentation for a class in Chinese using the Pinyin - Simplified input. It was late, I was tired, and somehow I pressed some combination of keys, and the little window that shows up with the different options of Chinese characters based on the pinyin typed disappeared! I have since learned that this window is called the candidate window.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-zAcvt5lOJFE/Tr7NkOgJKVI/AAAAAAAAA8w/wnXhWt-fa98/s1600/CandidateWindow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="82" src="http://3.bp.blogspot.com/-zAcvt5lOJFE/Tr7NkOgJKVI/AAAAAAAAA8w/wnXhWt-fa98/s320/CandidateWindow.png" width="320" /></a></div>
<br />
<br />
I googled and googled, and came across suggestions like:<br />
<br />
<ol>
<li>In the preferences for the input, switch the orientation of the input box from horizontal to vertical and then back again.</li>
</ol>
This didn't work for me. At first, as I typed the pinyin, my letters came out like regular Roman letters. And then after some futzing with the different preferences options, I ended up with getting letters like this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-X6omSmQzva8/Tr7NsGfYFtI/AAAAAAAAA84/GVBVfvmg46Y/s1600/Screen+shot+2011-11-12+at+2.39.37+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="39" src="http://1.bp.blogspot.com/-X6omSmQzva8/Tr7NsGfYFtI/AAAAAAAAA84/GVBVfvmg46Y/s320/Screen+shot+2011-11-12+at+2.39.37+PM.png" width="320" /></a></div>
<div>
<br /></div>
<div>
As it finally turns out, it seems I somehow I pressed the Caps Lock while in the Pinyin mode, which according to <a href="http://support.apple.com/kb/HT3560" target="_blank">this link</a> means I switched on the single-byte Roman character. Everything went back to normal after I reset my input preferences to the default. </div>
<div>
<br /></div>
<div>
So now I know how to be able to type regular Roman characters (i.e. English) while in Pinyin mode, which is to press the Caps Lock. As for the funky looking Roman characters I got, that happened when in my futzing with the preferences Options I selected "Use double-byte Roman characters":</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-rth5q0yRxNg/Tr7NuFYNipI/AAAAAAAAA9A/YKJcuMQGKMI/s1600/Screen+shot+2011-11-12+at+2.44.48+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://4.bp.blogspot.com/-rth5q0yRxNg/Tr7NuFYNipI/AAAAAAAAA9A/YKJcuMQGKMI/s320/Screen+shot+2011-11-12+at+2.44.48+PM.png" width="320" /></a></div>
<div>
<br /></div>
<div>
I have to say, I do like how Windows manages this particular input style. In the tool bar, Windows will tell you whether or not you are typing in English or Chinese when using the Pinyin input. There doesn't seem to be any indication on the Mac to show you this, unless you know that's what the Caps Lock is about. </div>
<div>
<br /></div>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-38207706777084397792011-10-17T16:29:00.000-04:002011-10-17T16:29:46.890-04:00Exporting RedNotebook notes to Evernote using ApplescriptI've recently switched my work environment from Ubuntu to Mac OS. While I was using Ubuntu, I used <a href="http://rednotebook.sourceforge.net/">RedNotebook</a> for taking notes about the various things I was working on, code snippets, to do lists, etc. I am now using <a href="http://evernote.com/">Evernote</a>, which has some nice features and better userability (in my opinion). Sadly, there is no easy way to import my notes from RedNotebook.<br />
<br />
What I've done to accomplish this is to use Mac's Applescript and I pieced together a hacky, but workable, way to do just this. It's not entirely pretty, and I'm sure it could be done better, but it does work with one caveat and some instructions (it's unfortunately not an entirely automatic procedure). So here it is for anyone else who wants an already working way to do the same thing.<br />
<br />
First off, the caveat: The very first note imported into Evernote ends up being an HTML attachment, instead of the text. And the formatting gets a little bit screwy in the imported files, but in my opinion, that's acceptable since what I want is to have this information for future reference.<br />
<br />
<br />
<ol>
<li>Create a new directory, this will be your input directory, and export the notebooks from RedNotebook you want imported as HTML. This will create one large XML file for all the notes for each notebook you want imported.</li>
<li>Create a new directory, this will be your output directory, and save <a href="https://sites.google.com/site/caffiendfrog/ribbit/evernoteexport/header.txt?attredirects=0&d=1">this file</a> to it. This file is the top portion of the xml file that will make up each of the individual notes in the evernote notes.</li>
<li>Download the <a href="https://sites.google.com/site/caffiendfrog/ribbit/evernoteexport/EvernoteImportRedNotebook.scpt?attredirects=0&d=1">applescript</a> or copy and paste from below to your computer.</li>
<li>Run the script, you will be prompted for the following:</li>
<ol>
<li>The header file, which is the template file you downloaded to your output directory.</li>
<li>The output directory you created.</li>
<li>The input directory containing the html files form RedNotebook</li>
</ol>
<li>Once the script is done, it is necessary to manually open the first exported file in your export directory and copy and paste this into the first note imported in Evernote, as mentioned earlier.</li>
</ol>
What the script does:<br />
<br />
<ol>
<li>Creates a new notebook in Evernote with the same name as the HTML file it is importing. If you have multiple HTML files, it will create a new notebook for each of these files.</li>
<li>For each HTML file, it will create a new note in the new notebook. The new note will be named the date the note was created and the creation date of the note will be modified to reflect this, so this metadata is not lost.</li>
</ol>
Here is the applescript code:<br />
<br />
<a name='more'></a><br />
<pre class="brush:bash">
set listOfNames to {}
set fileTemplate to choose file with prompt "Select the template file"
set templateLines to paragraphs of (read fileTemplate)
set outputFolder to choose folder with prompt "Select the output folder"
set createDate to current date
set createFileName to ""
set filelist to my getFileList(choose folder with prompt "Select the source folder")
repeat with currentFile in filelist
set headerSkipped to false -- skip the RedNotebook header
set headerContents to false -- drop the content between the top of the file and the RedNotebook header
set newFileLines to {templateLines}
set listFileNames to {}
-- read all the lines in the file
set myLines to readFile(currentFile as alias)
repeat with nextLine in myLines
set startTagLoc to (offset of "<h1>" in nextLine)
if startTagLoc > 0 then -- found header tag
if not headerSkipped then
set headerSkipped to true -- skip the initial RedNotebook header
else
set commaLoc to (offset of "," in nextLine)
set endTagLoc to (offset of "</h1>" in nextLine)
set dateString to text (commaLoc + 2) thru (endTagLoc - 1) of nextLine
-- set the create date and the filename to use
set createDate to my convertDate(dateString)
set createFileName to text (startTagLoc + 4) thru (endTagLoc - 1) of nextLine
set outputFileName to outputFolder & createFileName & ".html"
set listFileNames to listFileNames & outputFileName
if not headerContents then
set headerContents to true
else
if (count of newFileLines) > 0 then
my writeFile(newFileLines, outputFileName, currentFile, createDate, false)
my exportToEvernote(currentFile, outputFileName, createDate)
-- reset the list
set newFileLines to {templateLines}
end if
end if
end if
else
set newFileLines to newFileLines & nextLine
end if
headerSkipped
createDate
createFileName
end repeat
my writeFile(newFileLines, outputFileName, currentFile, createDate, true)
end repeat
on getFileList(inputFolder)
tell application "Finder"
set filelist to every file of the folder inputFolder
end tell
return filelist
end getFileList
on readFile(myFile)
tell application "Finder"
set myLines to paragraphs of (read myFile)
end tell
return myLines
end readFile
on convertDate(inputString)
return date (inputString)
end convertDate
on writeFile(newFileLines, newFileName, currentFile, createDate, isEof)
-- the following should actually be an end-div, end-body and end-html tags
set templateEnd to "</ div></ body></ html>"
set myFile to currentFile as alias
set finalText to {}
set end of finalText to newFileLines
set outFile to newFileName as text
if not isEof then
set finalText to finalText & templateEnd
end if
set AppleScript's text item delimiters to ASCII character 10
set myText to finalText as text
set AppleScript's text item delimiters to ""
set myFile to open for access outFile with write permission
write myText to myFile
close access myFile
return
end writeFile
on exportToEvernote(currentFile, newFileName, createDate)
set AppleScript's text item delimiters to ":"
set noteTitle to item 2 of newFileName
set notebookName to last text item of (currentFile as text)
set AppleScript's text item delimiters to ""
tell application "Evernote"
set theItem to create note title noteTitle created createDate notebook notebookName from file (newFileName as text)
end tell
return
end exportToEvernote
</pre><br />Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-5858371941095723652011-06-13T14:40:00.000-04:002011-06-13T14:40:31.608-04:00Setting up Apache CXF with SSL for client and serverI recently changed the JAXWS implementation from the reference implementation (RI) to Apache CXF. One of the motivating factors is that we need to be able to communicate via SSL, and to do this with the RI, the JVM system properties need to be changed. This can, and has, caused problems when the webapp shares Tomcat with other webapps.<br />
<br />
In order to this, I needed to set up Apache CXF. Specifically, our webapp acts as both a client and server.<br />
<br />
<br />
<span style="font-size: large;">1. Dependencies</span><br />
The first thing that needs to be done is to include the dependencies. We use maven.<br />
<br />
<div style="text-align: center;">
<i><span style="font-size: small;">(Defined in our <b>main</b> pom's properties section)</span></i>
</div>
<pre class="brush:xml"><properties>
<cxf-version>2.4.0</cxf-version>
</properties></pre>
<br />
<div style="text-align: center;">
<span style="font-size: x-small;"><i><span style="font-size: small;">(In the pom for any package that performs <b>client side</b> JAXWS actions)</span></i>
</span></div>
<pre class="brush:xml"><dependencies>
<dependency>
<groupid>org.apache.cxf</groupid>
<artifactid>cxf-rt-frontend-jaxws</artifactid>
<version>${cxf-version}</version>
</dependency>
<dependency>
<groupid>org.apache.cxf</groupid>
<artifactid>cxf-rt-transports-http</artifactid>
<version>${cxf-version}</version>
</dependency>
</dependencies></pre>
<br />
<div style="text-align: center;">
<i><span style="font-size: small;">(In the pom for the package that performs the <b>server side</b> JAXWS actions)*</span></i>
</div>
<pre class="brush:xml"><dependencies>
<dependency>
<groupid>org.apache.cxf</groupid>
<artifactid>cxf-rt-transports-http-jetty</artifactid>
<version>${cxf-version}</version> </dependency>
</dependencies></pre>
<br />
* I'm not 100% sure if this particular dependency is needed. It doesn't seem to be causing a problem with my build as of now. There is conflicting documentation about this. According to an out-dated <a href="http://cxf.apache.org/docs/using-cxf-with-maven.html">how to set up CXF with Maven</a>:<br />
<pre wrap=""></pre>
<pre wrap=""></pre>
<div style="text-align: center;">
<pre wrap="">Jetty is needed if you're using the CXFServlet</pre>
</div>
<div style="font-family: "Courier New",Courier,monospace; text-align: center;">
<pre wrap=""> </pre>
</div>
<pre wrap=""></pre>
However, according their <a href="http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/java_first_jaxws_factory_bean/pom.xml?view=co&revision=1091623&content-type=text%2Fplain">first jaxws factory bean sample</a> pom:<br />
<div style="text-align: center;">
<pre wrap=""> Jetty is needed if you're using the CXFServlet</pre>
</div>
<br />
I'll update this post when I find a definitive answer.<br />
<br />
<span style="font-size: large;">2. CXF Server Configuration</span><br />
<span style="font-size: small;">The next thing that needs to be done is to <a href="http://cxf.apache.org/docs/servlet-transport.html">register the cxf service</a>. This is done in the <span style="font-family: "Courier New",Courier,monospace;">WEB-INF</span> folder in the package that creates the web service <span style="font-family: "Courier New",Courier,monospace;">.war</span> file. This folder should contain two files:</span><br />
<ul>
<li><span style="font-size: small;">web.xml</span></li>
<ul>
<li><span style="font-size: small;">Registers the services</span></li>
</ul>
<li><span style="font-size: small;">cxf.xml</span></li>
<ul>
<li><span style="font-size: small;">Configuration file for cxf that tells cxf how to resolve the endpoint</span></li>
</ul>
</ul>
<div style="text-align: center;">
<span style="font-size: small;"><i>(web.xml)</i></span></div>
<pre class="brush:xml"><web-app id="MyWebAppName" version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>webservices-project</display-name>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/cxf.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app></pre>
<br />
Two things to note here:<br />
<ul>
<li>On line 6, there is a load-on-startup field. I'll be honest, I don't know what this does. According to the wise <a href="http://stackoverflow.com/questions/809775/what-does-the-servlet-load-on-startup-value-of-0-zero-signify">stackoverflow</a>:<br /><span style="font-family: "Courier New",Courier,monospace;">load-on-startup can specify an (optional) integer value. If the value is 0 or greater, it indicates an order for servlets to be loaded, servlets with higher numbers get loaded after servlets with lower numbers.</span></li>
<li>On line 14, this is the name and location of the configuration file for cxf. If your cxf config file is named differently, say cxf-mywebapp.xml, indicate it here.</li>
</ul>
<br />
<div style="text-align: center;">
<i>(cxf.xml)</i></div>
<pre class="brush:xml"><beans xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml">
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml">
<import resource="classpath:META-INF/cxf/cxf-servlet.xml">
<jaxws:endpoint address="/hello" id="MyWebAppName" implementor="org.my.webapp.MyWebAppImpl">
</jaxws:endpoint>
</import></import></import></beans></pre>
<br />
One thing to note here is:<br />
<ul>
<li>Line 11: Specify here the id/name of the web-service, the fully annotated for JaxWS implementation of the web-service and the address. </li>
</ul>
<br />
<span style="font-size: large;">3. Initialize conduit for SSL communication </span><br />
CXF has various methods for controlling settings for the communications. In order to set up the proxy for SSL communications, settings are made to the TlsClientParameters. I have the following method to set the TlsClientParameters for this (adapted from this <a href="http://mail-archives.apache.org/mod_mbox/cxf-users/200807.mbox/%3C48891BDE.70004@fluxcorp.com%3E">post</a>):<br />
<pre class="brush:java">public final class Utils
{
private static final TLSClientParameters tlsParams = new TLSClientParameters();
private static volatile boolean isTlsSetForSSL = false;
private static final Lock setTlsParamsLock = new ReentrantLock();
// ----
// Some other methods and things
// ---
static final TLSClientParameters getTlsParams()
{
return tlsParams;
}
static final void initializeConduitForSSL() throws Exception
{
// if the tls params have not been set up for SSL
if(!isTlsSetForSSL)
{
// get the lock
setTlsParamsLock.lock();
// intentionally checking twice to try to minimize overhead
// of acquiring lock
if(!isTlsSetForSSL)
{
try
{
isTlsSetForSSL = true;
// set up the keystore and password
KeyStore keyStore = KeyStore.getInstance("JKS");
// -- provide your password
String trustpass = "password";
// -- provide your truststore
File truststore = new File("truststore.jks");
keyStore.load(new FileInputStream(truststore), trustpass.toCharArray());
// should JSEE omit checking if the host name specified in the
// URL matches that of the Common Name (CN) on the server's
// certificate.
tlsParams.setDisableCNCheck(true);
// set the SSL protocol
tlsParams.setSecureSocketProtocol("SSL");
// set the trust store
// (decides whether credentials presented by a peer should be accepted)
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] tm = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(tm);
// set our key store
// (used to authenticate the local SSLSocket to its peer)
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, trustpass.toCharArray());
KeyManager[] km = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(km);
// set all the needed include & exclude cipher filters
FiltersType filter = new FiltersType();
//filter.getInclude().add(".*_WITH_3DES_.*"); // XXX needed?
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
}
catch(final Exception e)
{
throw new Exception("Failed to initialize conduit!", e);
}
finally
{
setTlsParamsLock.unlock();
}
}
}
}
}</pre>
<br />
Things to note: <br />
<ul>
<li><a href="http://www.blogger.com/%20http://cxf.apache.org/faq.html#FAQ-AreJAXWSclientproxiesthreadsafe%3F">According to CXF</a>, proxies can be thread safe, however settings on the conduit are <b>NOT</b>. The settings on the conduit are per instance. For this reason, I have done the following:</li>
<ul>
<li>There is a volatile variable isTlsSetForSSL that is checked so the settings are only made once.</li>
<li>The settings are done only after acquiring a lock</li>
</ul>
<li>The TlsClientParameters allow for setting two different stores, one for the keystore and one for the truststore. In this example, both of these happen to be the same file.</li>
<li>Line 63 is commented out. I'm not sure if this is needed or not. I was having some trouble getting this to work, and thought it was related to the filters that were included. I came across a <a href="http://cxf.547215.n5.nabble.com/CONF-Apache-CXF-Documentation-gt-Client-HTTP-Transport-including-SSL-support-td586029.html">post</a> that mentioned: <br /> <br />
<span style="font-size: x-small;"><span style="font-family: inherit;">2009-10-30 19:37:37:745 INFO [pool-2-thread-4] [PhaseInterceptorChain] - Interceptor has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not send Message.
....
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
</span><br style="font-family: inherit;" /><br style="font-family: inherit;" /><span style="font-family: inherit;">
Later I found out that the new server expected to communicate over a 3DES SSL cipher suite because the new Apache configuration was set to use strong encryption (see encryption http://httpd.apache.org/docs/2.2/ssl/ssl_howto.html).</span></span> <br /> <br /> In my case, it turned out that there was one place in the unit test that did not call this initializing method before making a proxy.</li>
</ul>
<span style="font-size: large;">4. Making a proxy to use</span><br />
<span style="font-size: small;">Prior to this change, we were using the reference implementation (<a href="http://jax-ws.java.net/">Sun</a>)</span>. In order to have SSL work properly in that implementation, it was necessary to make changes to the JVM wide system properties, which was un-desirable. When making the change to CXF, we were trying to limit the use of implementation specific code. <br />
<br />
CXF has an <a href="http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport%28includingSSLsupport%29-HowtoconfiguretheHTTPConduitfortheSOAPClient%3F">example</a> that shows how to configure the conduit for a client, and indirectly shows how to get a proxy to work with:<br />
<pre class="brush:java">import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
...
URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
SOAPService service = new SOAPService(wsdl, serviceName);
Greeter greeter = service.getPort(portName, Greeter.class);
Client client = ClientProxy.getClient(greeter);
HTTPConduit http = (HTTPConduit) client.getConduit();</pre>
<br />
Since our prior implementation used <span style="font-family: "Courier New",Courier,monospace;">javax.xml.ws.Service</span> to get the service, I decided to reuse that instead for getting the service:<br />
<pre class="brush:java">import javax.xml.ws.Service;
import javax.xml.namespace.QName;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
...
final QName qServiceName = new QName(myNamespace, serviceName);
final QName qPortName = new QName(myNamespace, portName);
final Service service = Service.create(myUrl, qServiceName);
final Greeter greeter = service.getPort(qPortName, Greeter.class);
Client client = ClientProxy.getClient(greeter);
HTTPConduit http = (HTTPConduit) client.getConduit();
// !! THIS DOES NOT WORK FOR SSL !!
http.setTlsClientParameters(getTlsParams());</pre>
<br />
After removing all the methods that set the system wide JVM properties and trying this out... it turns out that it <b>DOES NOT WORK</b>. The following is the stacktrace on the server's log of the failure: <br />
<pre class="brush:java">Caused by: javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:149)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:90)
at javax.xml.ws.Service.<init>(Service.java:56)
at javax.xml.ws.Service.create(Service.java:680)
... more
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:93)
at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:203)
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:147)
... 15 more
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://localhost:9081/node-server/node?wsdl'.: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:239)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:186)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:91)
... 17 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
... 41 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
... 47 more</init></init></init></init></init></pre>
<br />
As it turns out, it is failing at line 10 in the above, the <span style="font-family: "Courier New",Courier,monospace;">javax.xml.ws.Service</span> call does something that tries to connect before getting to the conduit set up. This call relies on the JVM system wide properties, and because I had removed this bit of code, it was failing because it could not longer find the keystore information on the properties.<br />
<br />
When I changed the code to use the implementation specific way of setting up a proxy, it worked:<br />
<pre class="brush:java">final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(Greeter.class);
factory.setAddress(myUrl.toString());
final Greeter greeter = (Greeter) factory.create();
final Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
// make sure to initialize tlsParams prior to this call somewhere
http.setTlsClientParameters(getTlsParams());</pre>
<br />
One final thing to note. In our unit test, we originally had:<br />
<pre class="brush:java">private static final String endpointA = protocol + "://localhost:9080/" + serverContext + "/node";</pre><br />
This resulted in the following error when trying to run the unit test after switching to CXF:<br /><pre class="brush:java">javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:149)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:90)
at javax.xml.ws.Service.<init>(Service.java:56)
at javax.xml.ws.Service.create(Service.java:680)
... more
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:93)
at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:203)
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:147)
... 32 more
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://localhost:9080/server/node'.: java.io.IOException: Server returned HTTP response code: 500 for URL: https://localhost:9080/server/node
at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:239)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:186)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:91)
... 34 more
Caused by: java.io.IOException: Server returned HTTP response code: 500 for URL: https://localhost:9080/server/node
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1436)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
... 40 more
</pre><br />
Chaniging the endpoint to add a ?wsdl to the end of the string fixed this problem: <br />
<pre class="brush:java">private static final String endpointA = protocol + "://localhost:9080/" + serverContext + "/node?wsdl";</pre> <br />
And that's it. Hopefully this helps.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com2tag:blogger.com,1999:blog-2587581514321322199.post-12416262343118346622011-05-26T16:07:00.001-04:002011-05-26T16:07:32.560-04:00Yourkit & Tomcat webapp on Fedora<a href="http://www.yourkit.com/">Yourkit</a> is a great tool for profiling Java applications. I'm using it to do some profiling on our webapp that is deployed in a Tomcat on a remote server (virtual machine on Rackspace). I've found that Yourkit is really simple and intuitive to use and set up, for the most part.<br />
<br />
The only issue I've had was getting it set up on the remote server to hook my local GUI to. Theoretically, it is a very simple <a href="http://www.yourkit.com/docs/95/help/profiling_j2ee_remote.jsp">process</a>. Download yourkit to the remote server, start up tomcat, and type the following at the command prompt:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<directory content="" unpacked="" with="">/bin/yjp.sh -integrate</directory></div>
<br />
I've <a href="http://www.yourkit.com/download/yjp-9.5.6-linux.tar.bz2">downloaded</a> & installed the linux version into my<span style="font-family: "Courier New",Courier,monospace;"> /opt/</span> folder on my remote server. My remote server is Fedora 14 64bit. When I run the above command, I get the following prompts:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-nrPrdYm-umc/Td6q45vkEzI/AAAAAAAAA44/5dnJmj2vucs/s1600/screenshot-yjp-integrate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="http://1.bp.blogspot.com/-nrPrdYm-umc/Td6q45vkEzI/AAAAAAAAA44/5dnJmj2vucs/s640/screenshot-yjp-integrate.png" width="640" /></a></div>
<br />
<br />
And here is where I run into a problem. Where is the tomcat <span style="font-family: "Courier New",Courier,monospace;">startup.sh</span>?? I do a search on the remote machine for the file and come up empty handed. I sift around online and come up empty handed. Finally after trial and error, I find that the file that is used on Fedora for starting up tomcat is called:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
/usr/sbin/tomcat6</div>
<br />
I would have thought this would be the end of it. Unfortunately, it looks the <span style="font-family: "Courier New",Courier,monospace;">-integrate</span> command munges the<span style="font-family: "Courier New",Courier,monospace;"> startup.sh </span>to add an additional JAVA_OPTS to create the hooks for Yourkit. And of course<span style="font-family: "Courier New",Courier,monospace;"> /usr/sbin/tomcat6</span> is not formatted how Yourkit is expecting the<span style="font-family: "Courier New",Courier,monospace;"> startup.sh</span> to be formatted. So no go.<br />
<br />
The next option is to <a href="http://www.yourkit.com/docs/95/help/agent.jsp">manually</a> add the JAVA_OPTS to the file. What I've done is add the following:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
-agentpath:/opt/yjp-9.5.6/bin/linux-x86-64/libyjpagent.so<span style="background-color: orange;">=port=10001</span></div>
<br />
after the {JAVA_OPTS} in the start block of the <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6</span> script (around line 30):<br />
<pre class="brush:bash">if [ "$1" = "start" ]; then
${JAVACMD} $JAVA_OPTS -agentpath:/opt/yjp-9.5.6/bin/linux-x86-64/libyjpagent.so=port=10001 $CATALINA_OPTS \
-classpath "$CLASSPATH" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
-Djava.util.logging.config.file="${CATALINA_BASE}/conf/logging.properties" \
-Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager" \
org.apache.catalina.startup.Bootstrap start \
>> ${CATALINA_BASE}/logs/catalina.out 2>&1 &
if [ ! -z "$CATALINA_PID" ]; then
echo $! > $CATALINA_PID
fi
</pre>
<br />
I have added an additional <a href="http://www.yourkit.com/docs/95/help/startup_options.jsp">startup option</a> to this, specifying the port to use. Pay close attention when inserting this option and be sure that is a <b>space between <span style="font-family: "Courier New",Courier,monospace;">$JAVA_OPTS</span> and <span style="font-family: "Courier New",Courier,monospace;">[agentpath]</span></b> as well as a <b>space between <span style="font-family: "Courier New",Courier,monospace;">[agentpath]</span> and <span style="font-family: "Courier New",Courier,monospace;">$CATALINA_OPTS</span></b>. Because I will not always want the agent attached (overhead and performance reasons), I created two copies of the tomcat6, a tomcat6_yourkit & tomcat6_orig (original tomcat6 file) that I copy to tomcat6 as needed to swap the configurations.<br />
<br />
Finally, the last thing that needs to be done is to open up the port in the iptables file on the remote server to allow the connection to be made.<br />
<br />
Summary:<br />
<ol>
<li><a href="http://www.yourkit.com/download/index.jsp">Download</a> the correct distribution for the remote server's platform to /opt/.<br /><div style="text-align: center;">
<span style="font-family: inherit; font-size: x-small;">(In my case I need the Linux distribution)</span></div>
<pre class="brush:bash">[root@bakeYourkit opt]# wget http://www.yourkit.com/download/yjp-9.5.6-linux.tar.bz2</pre>
</li>
<li>Extract the file.<br /><div style="text-align: center;">
<span style="font-size: x-small;">(In my case it is a tar.bz2, which I always forget <a href="http://www.cyberciti.biz/faq/install-tarballs/">how to</a> do).</span></div>
</li>
<li>Make a copy of <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6</span> as <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6_orig</span><br />
<pre class="brush:bash">[root@bakeYourkit ~]# cp /usr/sbin/tomcat6 /usr/sbin/tomcat6_orig</pre>
</li>
<li>Edit <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6</span>, save, and make a copy as <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6_yourkit</span><br /><pre class="brush:bash">[root@bakeYourkit ~]# vim /usr/sbin/tomcat6
[root@bakeYourkit ~]# cp /usr/sbin/tomcat6 /usr/sbin/tomcat6_yourkit
</pre>
</li>
<li>Edit the iptables to listen to the port specified in the startup option above (in my example here, port number 10001). See <a href="http://caffiendfrog.blogspot.com/2011/01/remote-debugging-webapp-in-tomcat-rhel.html">this post</a> for information about editing the iptables file.</li>
<li>Restart tomcat to pick up the options.</li>
<li>On your local machine, start up yourkit and connect to the remote server:<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-D9ieUQQVA_Y/Td6xtTZAXyI/AAAAAAAAA48/splUl32J_Mk/s1600/connect-to-remote.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="http://2.bp.blogspot.com/-D9ieUQQVA_Y/Td6xtTZAXyI/AAAAAAAAA48/splUl32J_Mk/s320/connect-to-remote.png" width="320" /></a></div>
</li>
</ol>
Ta-da! That's all. Now if you want to switch off the agent, copy the original /usr/sbin/tomcat6_orig over the /usr/sbin/tomcat6 file. There is definitely a nicer way to this, possibly by adding some environment variable and setting it to. But this works for me.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-88561552662357002262011-05-23T16:53:00.000-04:002011-05-23T16:53:17.973-04:00Perl script to "copy" a Rackspace image<br />
I recently found myself putting together a perl script that performs an rsync of one server in the Rackspace cloud to another server on another account. Why? See my next post about restrictions found with Rackspace for details. Long story short, I needed a way to copy an image from one account to another and Rackspace recommends using <a href="http://cloudservers.rackspacecloud.com/index.php/Migrating_a_Linux_Server_From_Command_Line_Stage_1">rsync</a>.<br />
<br />
Since I will be needing to do this at least once a month for my testing, I thought it best to write up a script using perl that does the rsync. The first thing was to figure out to successfully do this rsync before putting things together in a script. I followed the instructions and when I rebooted my new server with the files rsync'ed over, it failed to accept ssh anymore. On a whim, I decided to go through the basic exclude file from the instructions to see if those directories/files really lived where the file says they would be.<br />
<br />
Ah-ha! That was my problem. I'm not sure which distro was used to create the exclude file, but some of the recommended files/directories to be excluded were located in different places.<br />
<br />
<pre class="brush:bash">#Suggested by Rackspace
/etc/hostname
#Actual location on Fedora 14 64bit
/bin/hostname
#Suggested by Rackspace
/etc/modules
#Actual location on Fedora 14 64bit
/etc/sysconfig/modules</pre>
<br />
What I did was to do a <br />
<pre class="brush:bash">find / -name [sometext]</pre>
<br />
Where [sometext] I started from the end of the path and worked my way in to find the location. It was definitely trial and error. Here is what I have for my final exclude file for Fedora 14 64bit:<br />
<br />
<pre class="brush:bash">#exclude.txt
/proc
/sys
/tmp
/dev
/root/copyImage.log
/root/.ssh/
/var/lock
/etc/fstab
/etc/mtab
/etc/resolv.conf
/usr/share/dbus-1/interfaces
/etc/networks
/etc/sysconfig/network
/etc/sysconfig/network-scripts
/etc/sysconfig/iptables-config
/lib/modules/
/usr/share/selinux/devel/include/kernel
/bin/hostname
/usr/lib64/gettext/hostname
/etc/hosts
/etc/modprobe*
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/etc/sysconfig/modules
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/usr/lib64/gio/modules
/lib/udev/devices/net
/usr/lib/ruby/1.8/net
/etc/init/</pre>
<br />
So now that I have a working exclude file, the next thing was to code up a perl script to do this for me. In order to automate this through the script I needed to be able to:<br />
<ul>
<li>Create an ssh tunnel from the "sending" server to the "receiving" server and be able to generate an ssh key on the "receiving" server.</li>
<li>Add the "sending" server's public key to the "receiving" server's authorized_key file</li>
<ul>
<li>In my case, as part of the image, there is an authorized_key file with some public keys in it, which I want available to all servers generated with the image. I added the "sending" server's public key to this file and rsync'ed this file over first</li>
</ul>
<li>Rsync the "sending" server data to the "receiving" server.</li>
</ul>
Two of the largest hurdle is: <br />
<ol>
<li>Open the ssh connection to the "receiving" server</li>
<li>Know when the "receiving" server is asking for the password and supply it</li>
</ol>
There are many many perl modules available that do just this in various ways. I didn't think to make a note of which ones I did try, unfortunately. I ended up using <a href="http://search.cpan.org/%7Esalva/Net-OpenSSH-0.52/lib/Net/OpenSSH.pm">Net::OpenSSH</a>, it had the best documentation and did everything I needed. I used this in conjunction with <a href="http://search.cpan.org/%7Ergiersig/Expect-1.21/Expect.pod">Expect</a> module.<br />
<br />
<br />
Neither of these modules are included with the Perl package that comes with Fedora 14 64 bit. In trying to add these modules, I learned some more things. For example, I learned about <a href="http://search.cpan.org/">CPAN</a>. This is a little piece of software that manages installation and dependency resolution for perl modules. Other benefits I found are:<br />
<ul>
<li>Access to modules that may not be in repos yet, i.e. <span style="font-family: "Courier New",Courier,monospace;">Net::OpenSSH</span> is not available via yum on Fedora 14</li>
<li>Type in instmodsh at the command prompt and you can see a list of all installed modules and get information about the modules</li>
<ul>
<li>If module is installed via yum install , will not show up in instmodsh</li>
</ul>
</ul>
<a href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch06_:_Installing_Linux_Software#Automatic_Installation_of_Perl_Modules">Here</a> is a link describing how to install CPAN. After you follow the instructions at that link, you should also check to see if gcc is installed. In my case, it was also not included in my default Fedora 14 64bit installation. It is needed to compile some of the modules (in this case, one of the dependencies for <span style="font-family: "Courier New",Courier,monospace;">Expect</span>). The error I got before I installed it is:<br />
<br />
<pre class="brush:bash">ERROR: cannot run the configured compiler 'gcc'
(see conf/compilerok.log). Suggestions:
1) The complier 'gcc' is not in your PATH. Add it
to the PATH and try again. OR
2) The compiler isn't installed on your system. Install it. OR
3) You only have a different compiler installed (e.g. 'gcc').
Either fix the compiler config in the perl Config.pm
or install a perl that was built with the right compiler
(you could build perl yourself with the available compiler).
Note: this is a system-administration issue, please ask your local
admin for help. Thank you.
Warning: No success on command[/usr/bin/perl Makefile.PL]
'YAML' not installed, will not store persistent state
TODDR/IO-Tty-1.10.tar.gz
/usr/bin/perl Makefile.PL -- NOT OK
Could not read metadata file. Falling back to other methods to determine prerequisites
Failed during this command:
TODDR/IO-Tty-1.10.tar.gz : writemakefile NO '/usr/bin/perl Makefile.PL' returned status 6400
</pre>
<br />
Finally, my last hurdle for putting together this script is trouble using the <span style="font-family: "Courier New",Courier,monospace;">open</span> function in perl.<br />
<br />
<pre class="brush:bash">#DOES *NOT* WORK
open(CAT_FILE,"cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";
#DOES WORK
open(CAT_FILE,"| cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";</pre>
<br />
Can you spot the difference?<br />
So apparently that "<span style="font-family: "Courier New",Courier,monospace;">|</span>" is required ... oops...guess the <a href="http://www.perlhowto.com/executing_external_commands">documentation</a> was right. *insert chagrin here*.<br />
<br />
So without further ado, please find below my full script to do the rsync step of copying an image to another server on Rackspace:<br />
<br />
<a name='more'></a><br />
<pre class="brush:perl">#!/usr/bin/perl
use strict;
use Expect;
use Net::OpenSSH;
use POSIX qw(strftime);
# ---- start of main ---- #
# Input to script should be ipAddress pwd ipAddress pwd
# take arguments and put into a hash, {key=ipAddress, value=pwd}
my %args = @ARGV;
my @bad_args;
my $log_fname = "/root/copyImage.log";
my $user = "root";
open(LOG_FILE,">>".$log_fname);
# Do a simple check to make sure that the key of hash is
# IP-like (just checking it is ###.###.###.###) and the
# password is only alphanumeric
foreach my $key (keys(%args)) {
if (not $key =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
print LOG_FILE "[".get_timestamp()."]\t";
print LOG_FILE "Invalid IP address: ".$key."\n";
push(@bad_args,"Invalid IP, ".$key);
}
if (not $args{$key} =~ m/^[a-z0-9.-]+$/i) {
print LOG_FILE "[".get_timestamp()."]\t";
print LOG_FILE "Invalid password: ".$args{$key}."\n";
push(@bad_args,"Invalid password, ".$args{$key});
}
}
if (scalar(@bad_args) > 0) {
# at least one of the arguments is bad, safer to stop now
# close log file and exit
close(LOG_FILE);
exit(1);
}
# Comment out below to disable debugging
$Net::OpenSSH::debug |= 16;
# add local host pub key to authorized_keys file, so local host pub key is
# transferred when transferring authorized_keys file to remote host
my $cat_out = `cat /root/.ssh/id_rsa.pub >>/root/.ssh/authorized_keys`;
print "Concatenate local pubId to authorized keys file. [".$cat_out."]\n";
# now loop through the hash and do the work
foreach my $key (keys(%args)) {
# reassign key & value to make rest of code more readable
my $host = $key;
my $pwd = $args{$key};
my $opts = "StrictHostKeyChecking=no";
# set up the ssh connection to receiving host to do
# ssh key generation
my $ssh = Net::OpenSSH->new($host,user=>$user,password=>$pwd,
master_opts=>[-o=>$opts]);
$ssh->error and die "Couldn't establish connection: ".$ssh->error;
# send the ssh key generation down the pipe
my ($rout,$pid) = $ssh->pipe_out("ssh-keygen -t rsa -f /root/.ssh/id_rsa -P \"\"") or
die "Pipe out failed: ".$ssh->eror;
wait_pid_exit($rout, $pid, "Key generation");
# use rsync_put method to send rsync command via ssh
# send over the authorized keys file
my ($rout, $pid) = $ssh->rsync_put({stdout_fh => *STDOUT,
quiet=>0,
progress=>1,
archive=>1,
compress=>1,
partial=>1,
one_file_system=>1,
delete_after=>1},
"/root/.ssh/authorized_keys","/root/.ssh/authorized_keys");
wait_pid_exit($rout, $pid, "Rsync: authorized_keys");
# now rsync the rest of the files needed
my ($rout, $pid) = $ssh->rsync_put({stdout_fh => *STDOUT,
quiet=>0,
progress=>1,
archive=>1,
compress=>1,
partial=>1,
one_file_system=>1,
delete_after=>1,
exclude_from=>"/root/rsyncExclude.txt"},
"/","/");
wait_pid_exit($rout, $pid, "Rsync: rest of files");
# send command to delete the last line of the authorized_keys file
# down the pipe
my ($rout,$pid) = $ssh->pipe_out("sed '\$d' < /root/.ssh/authorized_keys > /root/.ssh/temp && mv -f /root/.ssh/temp /root/.ssh/authorized_keys") or die "Pipe out failed: ".$ssh->eror;
wait_pid_exit($rout, $pid, "Editing authorized_keys file");
my ($rout, $pid) = $ssh->pipe_out("exit") or
die "Pipe out failed: ".$ssh->error;
wait_pid_exit($rout, $pid, "Exiting ssh");
print "Exiting ssh.\n";
}
# Clean local authorized_key file by removing self from it
my $cat_out = `sed '\$d' < /root/.ssh/authorized_keys > /root/.ssh/temp && mv -f /root/.ssh/temp /root/.ssh/authorized_keys`;
print $cat_out."\nC'est fin!\n";
close(LOG_FILE);
exit(0);
# ---- end of main ----#
# ----sub routines start here ----#
# This method uses Expect to spawn a command line process on the local/this host/server
# that communicates to a remote/receiving host/server (i.e. rsync, ssh, etc.).
# The command will result result in a prompt on the local host for the remote host's password.
# and the method will wait for the prompt and provide the given password.
#
# Takes 2 parameters:
# 1 - The command string to be executed on the remote/receiving host/server
# 2 - The password to use
sub spawn_expect {
my ($command, $pwd, $ssh) = @_;
my @cmd = $command.split(/ /);
print "[".@cmd."]";
#my $exp = new Expect;
my ($pty, $pid) = ssh->open2pty(@cmd);
my $exp = Expect->init($pty);
#$exp->spawn($command);
$exp->expect(10,[ qr/password:\s*\z/ => sub { my $exp = shift;
$exp->send($pwd."\n"); } ] );
$exp->soft_close();
# wait for the process to complete
print "Waiting for pid [".$pid."] to exit...";
waitpid($pid, 0);
print "Spawning done.";
}
# Returns a local formatted timestamp string
sub get_timestamp {
return strftime "%a %b %e %Y %H:%M:%S", gmtime;
}
# waits for the given process id to exit
# uses given string to display helpful print out
sub wait_pid_exit {
my ($rout, $pid, $str_out) = @_;
while (<$rout>) { print } close $rout;
print "\nWaiting for pid [".$pid."] to exit...\n";
waitpid($pid, 0);
print $str_out." done.\n";
}
# ---- end of sub routines ---- #</pre>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-75167869100653063312011-02-15T18:57:00.001-05:002011-02-16T14:36:37.241-05:00Tomcat 6 & Fedora 14 frustrationsMore woes trying to set up a server image. Current pothole (as opposed to speed bump) is being brought to you by Tomcat 6 and Fedora 14. Having just gone through a whole lot of hoop-la getting java installed, I installed Tomcat with this simple command:<br />
<br />
<pre class="brush:bash">root@spin-1-16r tomcat6]# yum install tomcat6</pre>
<br />
<br />
<b>First woe:</b> <br />
My woes began when I tried to start up tomcat how I started it up on Rhel: <br />
<br />
<pre class="brush:bash">[root@spin-1-16r tomcat6]# tomcat6 start
/usr/sbin/tomcat6: line 30: /logs/catalina.out: No such file or directory
</pre>
<br />
<br />
What? How is an error happening when I haven't done anything but use the package installer yum to install tomcat? This time, I read my error carefully and decided to look in the file <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6</span>, line 30 for the offending code which was: <br />
<br />
<pre class="brush:bash"> org.apache.catalina.startup.Bootstrap start >> ${CATALINA_BASE}/logs/catalina.out
</pre>
<br />
<br />
Looking through the file, I don't see <span style="font-family: "Courier New",Courier,monospace;">CATALINA_BASE</span> defined. And then going back to the command prompt, I discover the environment variable <span style="font-family: "Courier New",Courier,monospace;">CATALINA_BASE</span> isn't defined anywhere: <br />
<br />
<pre class="brush:bash">[root@spin-1-16r webapps]# echo $CATALINA_BASE</pre>
<br />
<br />
More searching and I find that it <i><b>is</b></i> defined in <span style="font-family: "Courier New",Courier,monospace;">/etc/tomcat6/tomcat6.conf</span> and going back to the <span style="font-family: "Courier New",Courier,monospace;">/usr/sbin/tomcat6</span> file, I see that the following is commented out: <br />
<br />
<pre class="brush:bash"># Get the tomcat config (use this for environment specific settings)
#if [ -z "${TOMCAT_CFG}" ]; then
# TOMCAT_CFG="/etc/tomcat6/tomcat6.conf"
#fi
#
#if [ -r "$TOMCAT_CFG" ]; then
# . $TOMCAT_CFG
#fi
</pre>
<br />
<br />
Removing the comments from in front of lines 2-8 and saving solved this first issue.<br />
<br />
<b>*EDIT*</b><br /><b>Avoid first woe sub-part one:</b><br />
Remember earlier we went through some troubles to set up Sun's java and even set up some environment variables? We probably want to keep using Sun's java for tomcat. Open up the tomcat config file:<br /><pre class="brush:bash">[frog@caffiend ~]# less ~tomcat/conf/tomcat6.conf</pre> <br /> At the top of the file, after the comments about what file is for, you should see these lines: <br /><pre class="brush:bash"># Where your java installation lives
JAVA_HOME="/usr/lib/jvm/java"</pre><br />Now I'm not 100% that this will over-write the environment variable previously set, nor do I know whether or not that link will end up at the same location or not....so to be safe, I've commented it out on my server:<br /><pre class="brush:bash"># Where your java installation lives
#JAVA_HOME="/usr/lib/jvm/java"</pre><br />
<b>Second woe:</b><br />
Now the next woe began. For the purposes of work, the webapp war is dropped into the <span style="font-family: "Courier New",Courier,monospace;">/usr/share/tomcat6</span> folder and a symbolic link is created in the webapp folder pointing to the war. This is done because for our testing purposes, we swap various versions of the war, including snapshots, in and out and our deployment code to push out and configure multiple nodes have a hard link to the URL. We could always just change the name of the war to match what we have in the URL in our code, but then we would lose the quick at a glance sanity check of which version we are running. So that is what I did. And I started up tomcat, but EGADS, the war would <b>NOT</b> inflate and deploy. Why, oh why?<b> </b> After much googling on keywords like symbolic link not deploying war tomcat6 fedora14, so on and so forth...and bringing in a second pair of eyes...it hits me like a ton of bricks:<br />
<br />
<pre class="brush:bash">[root@spin-1-16r tomcat6]# ls -l webapps/
total 0
lrwxrwxrwx 1 root root 39 Feb 15 22:10 node-server -> /usr/share/tomcat6/node-server-1.16.war
</pre>
<br />
<br />
Do you see it now? It sure took me a while...my sym link did NOT end in .war. And that...is all it took. Changing the sym link and restarting tomcat my directory now looks like: <br />
<br />
<pre class="brush:bash">[root@spin-1-16r webapps]# ls -l
total 8
drwxr-xr-x 2 root root 4096 Feb 15 23:52 logs
drwxr-xr-x 4 root root 4096 Feb 15 23:52 node-server
lrwxrwxrwx 1 root root 39 Feb 15 23:52 node-server.war -> /usr/share/tomcat6/node-server-1.16.war
</pre>
<br />
<br />
And thus ends my woes. It looks so simple and duh all summed up here, but man, was it hard to see for me.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com5tag:blogger.com,1999:blog-2587581514321322199.post-61925016129183037532011-02-15T14:08:00.001-05:002011-02-16T14:38:06.631-05:00Ubuntu (v10.04) update frustrations<b>*EDIT*</b><br />
<i><span style="font-size: x-small;">I wrote this a few months back and I'm not quite sure why I never published it...might have been one of those days...hopefully it's correct, if it's not, please let me know.</span></i><br />
<i><span style="font-size: x-small;"> </span></i><b><br /></b><br />
Finally decided to do the updates that my Ubuntu has been asking me about for a week or so now. And of course, my Eclipse breaks because Ubuntu keeps trying to change my java to OpenJDK, which does <b>not</b> play together happily with Eclipse (v3.3). I'm sure others must also have this problem, so here is my step by step troubleshooting:<br />
<ol>
<li><i>Did the update change the environment variables?</i></li>
<ul>
<li>Check the bashrc file:<br />
<pre class="brush:bash">frog@caffiend:~$ vi ~/.bashrc
</pre>
<br />Where <span style="font-family: "Courier New",Courier,monospace;">vi<span style="font-family: inherit;"> is your console editor. You can use any editor you like. </span></span>The file <b>should</b> contain the following, most likely at the end:<br />
<pre class="brush:bash">export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.20/
</pre>
</li>
</ul>
<li><i>Did the update change the symbolic link?</i></li>
<ul>
<li>First find your Sun Java directory. I think it usually gets installed in <span style="font-family: "Courier New",Courier,monospace;">/usr/lib/jvm<span style="font-family: inherit;">. </span></span>One way is to do a search from the <span style="font-family: "Courier New",Courier,monospace;">FileSystem</span> using the File Browser for "sun". You're looking for a folder with a name like: <span style="font-family: "Courier New",Courier,monospace;">java-x-sun-n.n.nn<span style="font-family: inherit;">, where x is the version of java (nowadays, most likely 6...possibly 5) and n.n.nn is the release. </span></span></li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">Now check to make sure the java folder is pointing correctly to the alternatives folder:</span></span><br />
<pre class="brush:bash">frog@caffiend~:$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 2010-11-02 12:26 /usr/bin/java -> /etc/alternatives/java
</pre>
</li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">Now check where the alternatives folder is pointing to:</span></span><br />
<pre class="brush:bash">frog@caffiend~:$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 36 2010-11-02 12:26 /etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java
</pre>
</li>
<li>If one or both of these symbolic links are not pointing to the correct location:<br />
<pre class="brush:bash">frog@caffiend~:$ cd /usr/bin/
frog@caffiend~:$ sudo ln -f -s /etc/alternatives/java java
frog@caffiend~:$ cd /etc/alternatives/
frog@caffiend~:$ sudo ln -f -s /usr/lib/jvm/java-6-sun/jre/bin/java java
</pre>
</li>
</ul>
<li><i>Did the update change which Java is being used?</i></li>
<ul>
<li><pre class="brush:bash">frog@caffiend~:$ udo update-alternatives --config java
[sudo] password for frog:
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
0 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 auto mode
1 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 manual mode
* 2 /usr/lib/jvm/java-6-sun/jre/bin/java 63 manual mode
Press enter to keep the current choice[*], or type selection number: 2
</pre>
</li>
</ul>
<li><i>Confirm that the correct Java is being used</i>:</li>
<ul>
<li><pre class="brush:bash">frog@caffiend~:$ which java
/usr/bin/java
frog@caffiend:/usr/bin$ java -version
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Server VM (build 17.1-b03, mixed mode)
</pre>
</li>
</ul>
</ol>
Now try starting Eclipse. There is a chance you may still get an error if you use Maven, subclipse. A solution can be found <a href="http://islandlinux.org/howto/installing-javahl-subclipseeclipse-ubuntu">here</a>.<br />
<br />Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-25082618716613913652011-02-15T14:07:00.024-05:002011-02-16T14:27:06.585-05:00Errors Installing Java JDK on Linux.Several hours that I will never get back have just been lost due to errors received trying to install Sun's Java (specifically the JDK) on a virtual machine. I had previously been able to install the JDK without much of a hiccup last fall on the virtual machine at this particular vendor, and was quite puzzled as to why this was no longer working. Googling the error and various keywords didn't point out any obvious issues, everything seemed to say that Fedora 14 and Sun Java played well together, with the exception of having to configure the alternatives to point to the correct java (which I knew).<br />
<br />
<pre class="brush:bash">[root@spin-1 opt]# sh ./jdk-6u22-linux-i586.bin
Unpacking...
Checksumming...
Extracting...
./jdk-6u22-linux-i586.bin: ./install.sfx.20270: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
</pre>
<br />
Fine, let's try the self extracting rpm version:<br />
<pre class="brush:bash">[root@spin-1 opt]# sh ./jdk-6u22-linux-i586-rpm.bin
Unpacking...
Checksumming...
Extracting...
./jdk-6u22-linux-i586-rpm.bin: ./install.sfx.20566: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
Installing JavaDB
error: open of sun-javadb-common-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-core-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-client-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-demo-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-docs-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-javadoc-10.5.3-0.2.i386.rpm failed: No such file or directory
Done.
</pre>
<br />
After much googling, I kept coming back to this one <a href="http://forums.fedoraforum.org/showthread.php?t=205473">forum post</a>. In the middle of it, there is the following information from a poster:<br />
<br />
<span style="font-size: small;">"The library you are missing is comes from the 32bit version of the
glibc. You can try installing the i386 version of glibc using yum.
That would install /lib/ld-linux.so.2 for you."</span><br />
<br />
Great, so let's try installing the glibc ... (some of you may be seeing where this is going, but sadly I did not yet).<br />
<br />
<pre class="brush:bash">[root@spin-1 opt]# yum install glibc*</pre>
<br />
Alright, so now that's installed, I tried installing java again...to no avail. Scrolling back up the console to at the yum output from installing the glibc* I see:
<br />
<pre class="brush:bash">=============================================================================</pre>
<pre class="brush:bash"> Package Arch Version Repository Size
=============================================================================</pre>
<pre class="brush:bash">Installing:
gcc x86_64 4.5.1-4.fc14 fedora 14 M
Installing for dependencies:
cloog-ppl x86_64 0.15.7-2.fc14 fedora 93 k
cpp x86_64 4.5.1-4.fc14 fedora 4.0 M
glibc-devel x86_64 2.13-1 updates 968 k
glibc-headers x86_64 2.13-1 updates 599 k
kernel-headers x86_64 2.6.35.11-83.fc14 updates 742 k
libmpc x86_64 0.8.1-1.fc13 fedora 44 k
mpfr x86_64 2.4.2-1.fc13 fedora 158 k
ppl x86_64 0.10.2-10.fc12 fedora 1.1 M
Transaction Summary
=============================================================================</pre>
Now wait just a hot minute, why is it installing the x86_64 and not the i386 32bit ones....^Insert light bulb.<br />
<br />
That's right folks, the virtual machine is <b>64 bit</b> and I was trying to install a 32bit version of Java. Some time between when I last tried this particular exercise out on the vendor and now, the vendor moved from 32bit OS's to 64bit OS's. To verify:<br />
<br />
<pre class="brush:bash">[root@spin-1 opt]# uname -m
x86_64
</pre>
<br />
Well would you look at that, my vm's architecture is x86_64. :: sigh :: downloading the 64 bit version of Java JDK resolved the issues.<br />
<br />
For completeness of this post, some links to get started with Sun JDK Java and Tomcat 6 on Fedora 14, in order of things to do.<br />
<ol>
<li><a href="http://www.fedorafaq.org/#installsoftware">Configuring yum repositories on fedora</a></li>
<ul>
<li>On the remote machine, as root user, do the following: <br />
<pre class="brush:bash">yum --nogpgcheck install http://rpm.livna.org/livna-release.rpm http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm</pre>
</li>
</ul>
<li>On the remote machine, as root user, do the following: <br />
<pre class="brush:bash">yum update </pre>
<br />
</li>
<li>Download the 64 bit version of Java JDK desired onto local machine and then scp the file to the /opt directory of the remote machine<br /><br /></li>
<li>On the remote machine, possibly need to be remote user, do the following:<br /><pre class="brush:bash">[root@spin-1 opt]# sh ./opt/jdk-6u22-linux-x64.bin </pre>
<br />
</li>
<b>*EDIT*</b><br />
<span style="font-size: small;">(realized I also did the following and it is not included in the link at step 6, not entirely sure of the necessity, but I did this anyways just to make sure and everything is working)</span>
<li>Add the following environment variables (not included as part of the directions in 6, may not be 100% necessary, but I did this and everything work) to the <b><i>end of</i></b> <span style="font-family: "Courier New",Courier,monospace;">~/.bashrc</span>:<br /><pre class="brush:bash">export JAVA_HOME=/opt/jdk1.6.0_22
export JRE_HOME=${JAVA_HOME}/jre
export PATH=${JAVA_HOME}/bin:${PATH}
export CLASSPATH=${JAVA_HOME}/jre/lib:${CLASSPATH}
</pre>
<br />This is what my ~/.bashrc looks like:<br /><pre class="brush:bash"># .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
export JAVA_HOME=/opt/jdk1.6.0_22
export JRE_HOME=${JAVA_HOME}/jre
export PATH=${JAVA_HOME}/bin:${PATH}
export CLASSPATH=${JAVA_HOME}/jre/lib:${CLASSPATH}
</pre><br/>Save the file and from the command prompt, source the file:<br/>
<pre class="brush:bash">[root@newImage ~]# source ~/.bashrc
</pre><br/>Now do an echo to make sure the environment variable exists and points to the correct location:<br/>
<pre class="brush:bash">[root@newImage ~]# echo $JAVA_HOME
/opt/jdk1.6.0_22</pre><br />
You should see the location your jdk is installed, my jdk is installed in /opt/.<br/><b>N.B.</b>For the testing that we're doing here at work, we're always either logged in as root or tomcat is logged in as tomcat. I'm not familiar enough with environment variables and bash scripts to know where they need to be or what needs to be done to ensure the variable persists through all users.<br /><br />
</li>
<li>Follow the directions found <a href="http://www.if-not-true-then-false.com/2010/install-sun-oracle-java-jdk-jre-6-on-fedora-centos-red-hat-rhel/">here</a> for setting up the alternatives in Fedora to point to the correct java distro<br /><br /></li>
<li>Install tomcat: <br />
<pre class="brush:bash">yum install tomcat6*.*</pre>
<br />
</li>
</ol>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-20607633689434950462011-01-04T15:45:00.000-05:002011-01-04T15:45:02.101-05:00Remote debugging webapp in Tomcat (Rhel) through Eclipse (Ubuntu)Background to my current issue:<br />
There appears to be something odd going on the server side of our network code. Our server is a virtual machine hosted on GoGrid and the oddness is only occurring in release 1.14 and later of our network code. The current trunk of our code is 1.16-SNAPSHOT and the network code on the vm is 1.15 (release).<br />
<br />
I've spent the better of today getting right set of convocations together for my particular set of system set ups. Specifically:<br />
<b>Locally</b> <br />
* Ubuntu 10.04 (Lucid Lynx)<br />
* Eclipse 3.5<br />
<br />
<b>Server Side</b><br />
* Rhel 5.4<br />
<b> </b>* Tomcat 6<br />
<br />
Hopefully the following represents an accurate list of steps to assist anyone else with setting up a remote debugging of a webapp running on a Tomcat elsewhere through Eclipse on your local machine.<br />
<br />
<ul>
<li>Setting up tomcat to start up in debug mode:</li>
<ul>
<li> Most of the websites I came across suggest adding a command after the script:<br /> <br />
<pre class="brush:bash"> [host]$ catalina.sh jpda start </pre>
(<a href="http://blogs.mulesoft.org/debugging-your-tomcat-webapp-with-eclipse/">Mulesoft's blog</a>)</li>
</ul>
<ul>
<li>For my particular set up, I <i>did not</i> have a catalina.sh script
file to manipulate. Instead, Rhel's installation of Tomcat6 creates a
conf folder and a conf file where the options are set. In my case, the
specific file name is <span style="color: #274e13; font-family: "Courier New",Courier,monospace;">tomcat6.conf</span> and was found in <span style="color: #274e13; font-family: "Courier New",Courier,monospace;">~tomcat6/conf/</span></li>
<ul>
<li>In this file, I added the following lines after setting where the installation lives (noting that this should be the <b>first</b> JAVA_OPTS set):
<br /> <pre class="brush:bash"> # Java option to turn on debugger FIRST
JAVA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" </pre>
<br />
<span style="background-color: yellow;">NB: that there can </span><b style="background-color: yellow;">not</b><span style="background-color: yellow;"> be any spaces around the initial "=". </span> The above is NOT equivalent to:<br />
<pre class="brush:bash">JAVA_OPTS = "-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" </pre>
</li>
</ul>
<br />
<li>Now it's time to restart (bounce) the tomcat for the tomcat to pick up the changes in the JVM arguements: <br /> <pre class="brush:bash">[host]$ /etc/init.d/tomcat6 restart </pre>
</li>
</ul>
<br />
<li> Setting up the server to listen to the port that has been designated in the above step for the debugger (in this example, 8000<address=>, see the numbers after "address")</address=></li>
<ul>
<li>Now the appropriate ports need to be opened on the iptables:<br />
<pre class="brush:bash">[host]$ vim /etc/sysconfig/iptables </pre>
<br />
And add this line into the file and save it: <br />
<pre class="brush:bash">-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 8000 -j ACCEPT
</pre>
<br /> This line should go along with the other similar statements in the file. Once the file has been saved, the iptables need to be restarted for the changes to take affect: <br />
<pre class="brush:bash">[host]$ /etc/init.d/iptables restart</pre>
</li>
</ul>
<br />
<li>Since my server is hosted on GoGrid, I know that they have a firewall in place. The next step is to create an ssh tunnel to my server. For the sake of usability, I installed "<span style="font-family: "Courier New",Courier,monospace;">Gnome SSH Tunnel Manager - a front-end to ssh tunneling</span>" and added the information for my server and opened up the tunnel with the followinig for the properties:</li>
<ul>
<li>Name: GoGrid 252 [This can be anything that is easy for you to recognize]</li>
<li>Login: me [This is the login you would use to login to the server]</li>
<li>Host: ###.##.###.252 [This is the IP address of the server]</li>
<li>Port: 22 [This is the port that you have designated on your server as your ssh port, default is 22]</li>
</ul>
<br />
<li>Finally, on my local machine in Eclipse, I had to do the following:</li>
<ul>
<li>I needed the specific version of the code base project opened that the server was running. In this case, I had been working on 1.16 SNAPSHOT, which I needed to close and open up the 1.15 release that is running on the server.</li>
<li>Click on any file in the project that contains the webapp code</li>
<li>From the Eclipse menu, navigate: <span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">Run -> Debug Configurations</span></span></li>
<li><span style="font-family: inherit;">In the left handle panel, navigate up to <span style="font-family: "Courier New",Courier,monospace;">Remote Java Applications</span>, right click over it and select <span style="font-family: "Courier New",Courier,monospace;">New</span> from the pop-up menu.</span></li>
<li style="font-family: inherit;">In the right hand panel you should now see 3 tabs and a name field. The name field is for your reference and will show up on the left hand panel for you to select later. Under the <span style="font-family: "Courier New",Courier,monospace;">Connect</span> tab you should fill in the following:</li>
<ul>
<li style="font-family: inherit;">Project: [The project containing the source code for the webapp you are trying to debug in the remote Tomcat]</li>
<li style="font-family: inherit;">Connection Type: <span style="font-family: "Courier New",Courier,monospace;">Standard (Socket Attach)</span></li>
<li style="font-family: inherit;">Host: ###.##.###.252 [This is the IP address of the server]</li>
<li style="font-family: inherit;">Port: 8000 [This is the designated debugging port that was set up on the server]</li>
</ul>
<li style="font-family: inherit;">Click Apply and then Debug</li>
</ul>
<br />
<li style="font-family: inherit;">In the source code for the webapp, put a breakpoint somewhere that you know will be hit and then send a request to your tomcat. You should see be able to now debug in Eclipse.</li>
</ul>
<br />
And that summarizes up what I did to get the debugging to work on my local machine for a remote webapp on Tomcat.<br />
<br />
Here are some links to blogs which assisted me in getting to this point:<br />
<br />
<a href="http://forums.alfresco.com/en/viewtopic.php?f=10&t=1914&start=15">http://forums.alfresco.com/en/viewtopic.php?f=10&t=1914&start=15</a><br />
<a href="http://wiki.apache.org/tomcat/FAQ/Developing?highlight=%28CategoryFAQ%29">http://wiki.apache.org/tomcat/FAQ/Developing?highlight=%28CategoryFAQ%29</a><br />
<br />
Hope this helps :).Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com4tag:blogger.com,1999:blog-2587581514321322199.post-75963404774764019672010-11-08T14:06:00.001-05:002010-11-08T14:07:13.354-05:00Scala & Eclipse...Just keep cleaning...Today's aggravation is most likely brought to you by the Scala IDE (v1.0.0.201009232358) plugin for Eclipse (v3.5.2.R35). A simplified version of the offending code is:<br />
<pre class="brush:scala"> def nestedDoesntWork(num: Int) = {
if (true)
for (x <- 0 until num)
println(x)
}
</pre>
<br />
Where I have some condition that is checked and if true, proceeds into a for-loop. The error that I repeatedly get is:<br />
<ul style="color: red; font-family: "Courier New",Courier,monospace;">
<li>Exception in thread "main" java.lang.NoSuchMethodError: scala.collection.immutable.Range$ByOne.foreach$mVc$sp(Lscala/Function1;)V<br /> at org.spin.node.gogrid.Client$.doesntWork(Client.scala:62)<br /> at org.spin.node.gogrid.Client$.main(Client.scala:72)<br /> at org.spin.node.gogrid.Client.main(Client.scala)</li>
</ul>
However, this seems to work:<br />
<pre class="brush:scala"> def nestedWorks(num: Int) = {
if (true)
for (x <- (0 until num).toList)
println(x)
}
</pre>
<br />
Very odd. Even odder is if I define either of these functions on the Scala interpreter in Eclipse, they work fine. It's only when the <span style="font-family: "Courier New",Courier,monospace;">nestedDoesntWork</span> is defined within a class and I try to run a main function calling that class. The same happens if I take out the <span style="font-family: "Courier New",Courier,monospace;">if(true)</span> line.<br />
<br />
Solution? Clean project...and look, everything is fine and dandy. Make a change, get the error? Clean the project, and hurray. Note that the <span style="font-family: "Courier New",Courier,monospace;">nestedWorks</span> always works...without cleaning.<br />
<br />
Annoying to say the least, but today's lesson is if it doesn't work when it should the first time, clean the project. If it still doesn't work, clean it again. and again. and again.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-36628891167350334322010-11-01T17:43:00.003-04:002010-11-01T18:03:19.847-04:00Scala & Json (Lift-web): Trouble with "mapping" field name to another nameThis is a trivial mistake that just ate up the last 2 hours of my life that I will never get back again.<br />
<br />
One thing that is important is to be able to take the "raw" parsed json object and rename some of the fields since GoGrid uses some names that are reserved and/or have other Scala meanings. For example, GoGrid uses <span style="font-family: "Courier New",Courier,monospace;">Object<span style="font-family: inherit;"> and <span style="font-family: "Courier New",Courier,monospace;">Option<span style="font-family: inherit;"> to mean things specific to their environment. </span></span></span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">This is possible by using the </span></span></span></span><a href="http://github.com/jonifreeman/liftweb/tree/master/lift-json/">JValue's map function to postprocess AST</a>. Following the example in the readme documenation, I reproduced the following:<br />
<pre class="brush:scala">package org.gogrid.sandbox
abstract class jsonSandbox
{ }
case class Person(firstname: String)
</pre>
<br />
And then started up the Scala interpreter: <br />
<pre class="brush:scala">Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import org.gogrid.sandbox._
scala> import net.liftweb.json.JsonParser._
import net.liftweb.json.JsonParser._
scala> implicit val formats = net.liftweb.json.DefaultFormats
formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@1c9fe7e
scala> val jsonString = """ { "first-name" : "Jim" } """
jsonString: java.lang.String = { "first-name" : "Jim" }
scala> val json = parse(jsonString)
json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(first-name,JString(Jim))))
scala> json map {
| case JField("first-name", x) => JField("firstname", x)
| case x => x
| }
<console>:16: error: not found: value JField
case JField("first-name", x) => JField("firstname", x)
^
</pre>
<br />
Heh? Why is JField not found???<br />
<br />
My "Oh DUH moment":<br />
<br />
<div style="text-align: center;">
<b>I did NOT import the package where things like JField, JArray are defined.</b></div>
<div style="text-align: left;">
<b> </b></div>
<div style="text-align: left;">
Insert <a href="http://www.wallbash.com/">wall bash</a> here.<b> </b></div>
<pre class="brush:scala">
scala> import net.liftweb.json.JsonAST._
import net.liftweb.json.JsonAST._
scala> json map {
| case JField("first-name", x) => JField("firstname", x)
| case x => x
| }
res4: net.liftweb.json.JsonAST.JValue = JObject(List(JField(firstname,JString(Jim))))
</pre> <br />
Dang it.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-60172527561728660112010-11-01T13:27:00.000-04:002010-11-01T15:02:01.423-04:00Scala & Json (Lift-web): Trouble with getting startedI'm abandoning using XML parsing for this project. While I can get the results back from GoGrid now, I can't seem to figure out a simple, clean way to get the result string transformed into the objects for manipulation in our code. GoGrid has the XML set up as basically key value pairs, where for each object 'type' is specified as an attribute to the element, which makes squishing the result string through something to pop out an object at the end kind of an ugly hassle.<br />
<br />
GoGrid does provide the default response format to be Json, so I'm now chasing down this avenue.<br />
<br />
First up is to find an appropriate library to handle the heavy lifting, and for this I'm using <a href="http://liftweb.net/index">Lift-Web's Json library</a>. Lift-web is a large project made up of several projects, for my purposes, I only need the Json module. It took a little bit of scrounging around the net, but I found that what I need is the <span style="font-family: "Courier New",Courier,monospace;">lift-json<span style="font-family: inherit;"> module. The getting started documentation that I found on lift-web's site tells you how to set up a project from scratch, which is not what I need. I just needed access to this particular lib. After browsing their <a href="http://www.jarvana.com/jarvana/browse/net/liftweb/">source tree</a></span></span>, I decided to just put the information into my project's pom that I found <a href="http://www.jarvana.com/jarvana/inspect-pom/net/liftweb/lift-json/2.0-RC2/lift-json-2.0-RC2.pom">here</a> combined with the announcement that <a href="http://liftweb.net/21_ga">Lift-Web 2.1 has been released</a> and inserted the following into my pom:<br />
<pre class="brush:xml">//DOES NOT WORK
<dependency>
<groupid>net.liftweb</groupid>
<artifactid>lift-json</artifactid>
<version>2.1</version>
</dependency>
//DOES NOT WORK
</pre>
This (as the comments note) does not work. I ended up with the following error when I tried to save the pom:<br />
<div style="color: red; font-family: "Courier New",Courier,monospace; text-align: center;">
<br /></div>
<div style="color: red; font-family: "Courier New",Courier,monospace; text-align: center;">
Missing artifact net.liftweb:lift-json:jar:2.1:compile</div>
<br />
Okay, so that didn't work. So then I tried using version 2.0 instead to see if that will work:<br />
<pre class="brush:xml">//SORT OF WORKS
<dependency>
<groupid>net.liftweb</groupid>
<artifactid>lift-json</artifactid>
<version>2.0</version>
</dependency>
//SORT OF WORKS
</pre>
<br />
Well this <i>seemed</i> promising. I was able to save the pom with no errors. So the next step was to give the JsonParse -ing a whirl in the command line Scala interpreter (Eclipse v3.5.2 with Scala IDE for Eclipse v1.0.0.201009232358 plugin). I found an example on <a href="http://stackoverflow.com/questions/927983/how-can-i-construct-and-parse-a-json-string-in-scala-lift">Stackoverflow</a> and tried it out for myself:<br />
<pre class="brush:scala">scala> import net.liftweb.util.JSONParser
<console>:8: error: value util is not a member of package net.liftweb
import net.liftweb.util.JSONParser
</console></pre>
<br />
Um, okay. So that didn't work. Looking through the library that I added, I decided to try this next:<br />
<pre class="brush:scala">scala> import net.liftweb.json
import net.liftweb.json
scala> val jStr = """ { "name" : "Jim Bob" } """
jStr: java.lang.String = { "name" : "Jim Bob" }
scala> json.JsonParser.parse(jStr)
error: error while loading JsonParser, Scala signature JsonParser has wrong version
expected: 5.0
found: 4.1 in /home/sophia/.m2/repository/net/liftweb/lift-json/2.0/lift-json-2.0.jar(net/liftweb/json/JsonParser.class)
</pre>
Heh?! What the heck is going on? After some more fruitless searching on the web, I looked back at this <a href="http://www.jarvana.com/jarvana/browse/net/liftweb/">site</a> and saw that there was also a<span style="font-family: "Courier New",Courier,monospace;"> lift-json_2.8.0</span> package. I am using Scala 2.8.0 ... so I changed my pom to:<br />
<pre class="brush:xml">//SUCCESS!!
<dependency>
<groupid>net.liftweb</groupid>
<artifactid>lift-json_2.8.0</artifactid>
<version>2.1</version>
</dependency>
//SUCCESS!!
</pre>
And... Hurray! That did the trick:<br />
<pre class="brush:scala">scala> import net.liftweb.json
import net.liftweb.json
scala> val jStr = """ { "name" : "Jim Bob" } """
jStr: java.lang.String = { "name" : "Jim Bob" }
scala> json.JsonParser.parse(jStr)
res5: net.liftweb.json.JsonAST.JValue = JObject(List(JField(name,JString(Jim Bob))))
</pre>
<br />
Another note for getting started is that the string that is being parsed can be escaped or not, they both work:<br />
<pre class="brush:scala">//Un-escaped quotes in json string
scala> val jStr = """ { "name" : "Jim Bob" } """
jStr: java.lang.String = { "name" : "Jim Bob" }
scala> json.JsonParser.parse(jStr)
res5: net.liftweb.json.JsonAST.JValue = JObject(List(JField(name,JString(Jim Bob))))
//Escaped quotes in json string
scala> val badJstr = " { \"name\" : \"Jim Bob\" } "
badJstr: java.lang.String = { "name" : "Jim Bob" }
scala> json.JsonParser.parse(badJstr)
res6: net.liftweb.json.JsonAST.JValue = JObject(List(JField(name,JString(Jim Bob))))
</pre>
So the next thing on the list is to take a Json string, parse it and shove it into an object. An example of this can be found on <a href="http://github.com/jonifreeman/liftweb/tree/master/lift-json/">lift-web's source code site</a> and scroll down to extraction. I decided to go for a very simple test, using just a list of numbers (I'm still on the console in Eclipse with Scala interpreter):<br />
<pre class="brush:scala">scala> import net.liftweb.json.JsonParser._
import net.liftweb.json.JsonParser._
scala> implicit val formats = net.liftweb.json.DefaultFormats
formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@7db754
scala> case class Winn(numbers : List[Int])
defined class Winn
scala> val jsonStr = """{ "numbers" : [1,2,3,4] } """
jsonStr: java.lang.String = { "numbers" : [1,2,3,4] }
scala> val json = parse(jsonStr)
json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(numbers,JArray(List(JInt(1), JInt(2), JInt(3), JInt(4))))))
scala> json.extract[Winn]
net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor
args=
arg types=
constructor=public Winn(scala.collection.immutable.List)
at net.liftweb.json.Meta$.fail(Meta.scala:128)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:200)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:222)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:240)
at net.liftweb.json.Extraction$.extract(Extraction.scala:284)
at net.liftweb.json.Extraction$.extract0(Extraction.scala:172)
at net.liftweb.json.Extraction$.extract(Extraction.scala:40)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:288)
at .<init>(<console>:17)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at...
</console></clinit></console></init></console></clinit></console></init></pre>
<br />
So close...but not quite there. Back to the googling board. I eventually found <a href="http://markmail.org/message/ne2lrh4opzvgeui3">this</a> in lift-web's markmail and they say that:<br />
<br />
"The extraction feature uses paranamer to reflectively read the
constructor parameter names. Unfortunately paranamer lib does not work
with Scala console. Your example should work if you put your case
class definitions into .scala file and then import those after
compilation."<br />
<br />
Okay, so now I created a new scala file in my project that contains the following case class:<br />
<pre class="brush:scala">package org.gogrid.sandbox
abstract class jsonSandbox
{ }
case class Winn(numbers : List[Int])
</pre>
<br />
And then stopped the previous Scala interpreter and then right clicked over the package containing my sandbox class in the package explorer and started up a new Scala interpreter from there:<br />
<pre class="brush:scala">Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.
import org.gogrid.sandbox._
scala>
scala> Winn
res0: org.gogrid.sandbox.Winn.type = &ltfunction1>
scala> import net.liftweb.json.JsonParser._
import net.liftweb.json.JsonParser._
scala> implicit val formats = net.liftweb.json.DefaultFormats
formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@166de01
scala> val jsonStr = """{ "numbers" : [1,2,3,4] } """
jsonStr: java.lang.String = { "numbers" : [1,2,3,4] }
scala> val json = parse(jsonStr)
json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(numbers,JArray(List(JInt(1), JInt(2), JInt(3), JInt(4))))))
scala> val w = json.extract[Winn]
w: org.spin.node.gogrid.objects.Winn = Winn(List(1, 2, 3, 4))
scala> w.numbers
res3: List[Int] = List(1, 2, 3, 4)
scala> w.numbers(0)
res4: Int = 1
</pre>
<br />
That's the best "Int = 1" I've seen in a long time :) .<br />
<br />
So to summarize, to get started:<br />
<ol>
<li>Add a dependency on lift-json_2.8.0, version 2.1<br /><pre class="brush:xml"><dependency>
<groupid>net.liftweb</groupid>
<artifactid>lift-json_2.8.0</artifactid>
<version>2.1</version>
</dependency>
</pre>
</li>
<li>You can choose to escape or not the quotes within the json string, they both work.<br />
<pre class="brush:scala">scala> val jStr = """ { "name" : "Jim Bob" } """
jStr: java.lang.String = { "name" : "Jim Bob" }
scala> val badJstr = " { \"name\" : \"Jim Bob\" } "
badJstr: java.lang.String = { "name" : "Jim Bob" }
</pre>
</li>
<li>Case classes that represent the objects you are munging the string into cannot be defined in the class you are using them (and also can not be defined in the Scala interpreter of Eclipse).</li>
<li>Must include the implicit formats line of code <br />
<pre class="brush:scala">implicit val formats = net.liftweb.json.DefaultFormats </pre>
<br /> Otherwise you will get this error: <div style="color: red; font-family: "Courier New",Courier,monospace;">
error: could not find implicit value for parameter formats: net.liftweb.json.Formats</div>
</li>
</ol>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com4tag:blogger.com,1999:blog-2587581514321322199.post-10231318187657556622010-10-25T17:11:00.000-04:002010-10-25T17:14:48.997-04:00Scala, Jax-RS, and GoGrid: Trouble w/calculating signatureToday's lesson: Not all time is created equally.<br />
<br />
One important task for connecting to the GoGrid API is calculating your signature. From <a href="http://wiki.gogrid.com/wiki/index.php/API:Anatomy_of_a_GoGrid_API_Call#MD5_Signature">their documentation</a>, this is calculated by:<br />
<br />
<span style="font-family: inherit;"><i>"</i></span><i>generating an MD5 hash made up by concatenating the <b>API key</b>, the API user's
<b>shared secret</b>, and a <b>UNIX timestamp</b> reflecting the number of seconds since the Unix Epoch (January 1 1970 00:00:00
GMT) when the request is made.</i>"<br />
<br />
The keyword in this definition is: <b>seconds since the Unix Epoch</b>.<br />
<br />
Unfortunately, I did not read this definition closely, and naively translated my already working Python implementation:<br />
<pre class="brush:python">import md5
import time
class GoGridClient:
"""sample gogrid api client"""
api_key = 'xxxxxxxxxxx'
secret = 'someonesSecret'
....
def getSignature(self,key,secret):
""" create sig from md5 of key + secret + time """
m = md5.new(key+secret+str(int(time.time())))
return m.hexdigest()
</pre>
<br />
to the following Scala implementation, with a little help from <a href="http://code-redefined.blogspot.com/2009/05/md5-sum-in-scala.html">Code Redefined's post</a> for calculating the MD5 sum in Scala:<br />
<pre class="brush:scala">import java.security.MessageDigest
object BrokenClient {
val apiKey = "xxxxxxxxxxx"
val apiSecret = "someonesSecret"
val apiSignature: String = {
// m = md5.new(key+secret+str(int(time.time())))
val signature = MessageDigest.getInstance("MD5")
val timeStamp = System.currentTimeMillis().toString //<-- WRONG!!!!
signature.update(apiKey.getBytes)
signature.update(apiSecret.getBytes)
signature.update(timeStamp.getBytes)
signature.digest().map(0xFF & _).map { "%02x".format(_) }.foldLeft("") { _ + _ }
}
}
</pre>
<br />
And sadly kept getting a 403: Authentication Failed error. The correct way to implement this is:<br />
<pre class="brush:scala">import java.security.MessageDigest
object BrokenClient {
val apiKey = "xxxxxxxxxxx"
val apiSecret = "someonesSecret"
val apiSignature: String = {
// m = md5.new(key+secret+str(int(time.time())))
val signature = MessageDigest.getInstance("MD5")
val timeStamp = ((java.util.Calendar.getInstance(TimeZone.getTimeZone("GMT-0:00")).getTimeInMillis()) / 1000).toString //<-- YAY ^_^
signature.update(apiKey.getBytes)
signature.update(apiSecret.getBytes)
signature.update(timeStamp.getBytes)
signature.digest().map(0xFF & _).map { "%02x".format(_) }.foldLeft("") { _ + _ }
}
}
</pre>
<br />
Note that there is some kinda weirdness going on, in that <span style="font-family: "Courier New",Courier,monospace;">timeStamp</span> works even if you don't pass in a time zone, or if you pass in a random time zone.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-91185478310117321742010-10-25T11:40:00.000-04:002010-10-25T16:53:32.022-04:00Scala, Jax-RS, and GoGrid: Trouble with annotations<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
At the moment, I am trying to create a scala client that talks to GoGrid using their REST-like API. I am using Apache's Jax-RS implementation. There are examples (<a href="http://cxf.apache.org/docs/jax-rs.html#JAX-RS-ClientAPI">here</a> and <a href="http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features">here</a>) available online on how to use the Apache implementation to create a Java client and I have been trying to adapt these examples to Scala.<br />
<br />
One annoyance I have encountered so far is how to convert:<br />
<pre class="brush:java">@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
@GET
public String doGetAsPlainText() {
...
}
}
</pre>
<br />
My first pass at this is:<br />
<pre class="brush:scala">import javax.ws.rs.{ Path, GET, Produces }
@Path("grid/server/list")
@Produces("text/plain")
class ListRequest {
@GET
var plainText : String = _
}
</pre>
<br />
Which produces an obscure error (or at least obscure to me):<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><img \{<error>\}="" alt="annotation argument needs to be a constant; found: \" border="0" height="158" plain\="" src="http://4.bp.blogspot.com/_l3ER0fhcBrQ/TMWicgGpFsI/AAAAAAAAAt4/cdcB88Q7ygM/s640/scala-e1.jpg" style="margin-left: auto; margin-right: auto;" text="" width="640" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Error: "annotation argument needs to be a constant; found: "text/plain" {<<error>error>}</error></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/_l3ER0fhcBrQ/TMWicgGpFsI/AAAAAAAAAt4/cdcB88Q7ygM/s1600/scala-e1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a></div>
After trying a variety of things to make this acceptable for Scala and a lot of time searching to no avail, I randomly came across this <a href="http://github.com/jboner/akka/blob/master/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala">post</a>, where the author is trying to do something similar and found out that the code needs to look like this:<br />
<pre class="brush:scala">import javax.ws.rs.{ Path, GET, Produces }
@Path("grid/server/list")
@Produces(Array("text/plain"))
class ListRequest {
@GET
var plainText : String = _
}
</pre>
<br />
Note that <span style="font-family: "Courier New",Courier,monospace;">"text/plain"<span style="font-family: inherit;"> is now an element of an array...so apparently when the error says that the argument needs to be a constant...it meant it needs to be in an Array. Okay...</span></span>Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0tag:blogger.com,1999:blog-2587581514321322199.post-1077740298867189552010-10-22T18:54:00.000-04:002010-10-25T11:02:13.931-04:00SyntaxHighlighter and BloggerIronically, it took me a little while to futz around with syntaxHighlighter to get it to work nicely with blogger so I could post my first post...which will now be my second post since my first post is now going to be about syntaxhighlighter and blogger.
After a little bit of googling, I found myself at this very helpful post from <a href="http://developertips.blogspot.com/2007/08/syntaxhighlighter-on-blogger.html">Tips for software engineer</a>. However, as I'm sure many of you fellow googlers have found out, sometimes these helpful posts are slightly dated and don't have up to date information on how to get things done. Following the directions on his post, I attempted my first test post by copying and pasting from some xml from <a href="http://projects.gnome.org/gedit/">Gedit</a>. And for some reason, I ended up with:
<br />
<pre class="brush:xml"><configuration>
<sources>
<source>src/main/scala</source>
</sources>
</configuration>
</pre>
<br />
For whatever reason, there was an extra line break inserted between each of these lines...which was driving me crazy. That's not very useful at all for copying and pasting.
After a bit more searching, it turns out SyntaxHighlighter now has a fix for the extra <br /> that Blogger inserts into posts which causes the extra line breaks:<br />
<pre class="brush:javascript"><script language="javascript">
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://where.your.stuff/is/hosted/syntaxhighlighter/clipboard.swf';
SyntaxHighlighter.all();
</script>
</pre>
<br />
Note the "dp.SyntaxHighlighter.BloggerMode();" on line 2. Now this is looks all great and dandy, however...my first tests posts <b>*still*</b> had the annoying extra line breaks. The solution appears to be changing some 'default' blogger settings. Expand the <b><u>Post Options</u></b> underneath the box where you are entering your post and make sure that [<i style="font-family: Arial,Helvetica,sans-serif;">Use <br / > tags</i><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-family: inherit;">]</span></span><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-family: inherit;"> is selected for </span><span style="font-family: "Courier New",Courier,monospace;">Edit HTML Line Breaks<span style="font-family: inherit;">.</span></span></span><br />
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<br /></div>
<pre class="brush:xml"> <configuration>
<sources>
<source>src/main/scala</source>
</sources>
</configuration>
</pre>
<br />
<br />
Ah, much better.<br />
<br />
Of course while I am trying to write this post, I realized that <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a> has a new website with a new version and new functionality, which for whatever reason is <b>*not* </b>the first result returned in google...okay, it's the third. Anyways, to add to the plethora of available step by step instructions available for getting SyntaxHighlighter to work with Blogger that worked for me:<br />
<br />
<ol>
<li> Download the latest release <a href="http://alexgorbatchev.com/SyntaxHighlighter/download/download.php?sh_current">here</a> as well as an older release <a href="http://code.google.com/p/syntaxhighlighter/downloads/detail?name=SyntaxHighlighter_1.5.1.rar">here</a>.</li>
<li>Unzip the files and then upload the following to a host of your choice (I use <a href="https://sites.google.com/site/sites/">Google Sites</a>, yay for free! <b>EDIT: <i>Site must be viewable by public</i></b>):</li>
<ul>
<li>From the current release folder: </li>
</ul>
<ul><ul>
<li><span style="font-family: "Courier New",Courier,monospace;">shcore.css</span><span style="font-family: inherit;"> - Core stylesheet</span></li>
<li><span style="font-family: "Courier New",Courier,monospace;">shThemeDefault.css </span>- At least one theme, I chose the default theme. <span style="font-family: inherit;"> </span></li>
<li><span style="font-family: "Courier New",Courier,monospace;">shCore.js</span> - Core javascript</li>
<li><span style="font-family: "Courier New",Courier,monospace;">shBrushXML.js</span> - As many javascript brushes as you want, </li>
</ul>
<li><span style="font-family: inherit;"> </span>From the older release folder:</li>
<ul>
<li><span style="font-family: "Courier New",Courier,monospace;">clipboard.swf</span> - code to enable clipboard, not sure why is not included in the current release folder.</li>
</ul>
</ul>
<li>In your Blogger account, go to the <u><b><span style="font-family: "Courier New",Courier,monospace;">Design</span></b></u><b style="font-family: inherit;"> </b><span style="font-family: inherit;">tab, and then select the <u><b style="font-family: "Courier New",Courier,monospace;">Edit HTML</b></u></span><b style="font-family: inherit;"> </b><span style="font-family: inherit;">sub-tab</span><span style="font-family: inherit;"></span>.</li>
<li>Download your template as it is now somewhere in case everything goes whacky and you need to go back to the original.</li>
<li>Insert the following code snippet into the Edit Template box just before the <span style="font-family: "Courier New",Courier,monospace;"><b></body></b> </span>tag.
<pre class="brush:javascript">
<link href='http://where.your.stuff/is/hosted/syntaxhighlighter/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://where.your.stuff/is/hosted/syntaxhighlighter/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shCore.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushBash.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushJava.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushJScript.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushPerl.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushPhp.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushPython.js'/>
<script type="text/javascript" src='http://where.your.stuff/is/hosted/syntaxhighlighter/shBrushXml.js'/>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://where.your.stuff/is/hosted/syntaxhighlighter/clipboard.swf';
SyntaxHighlighter.all();
</script>
</pre>
</li>
<li>Save the template </li>
<li>When you go to make your first post using this, make sure that under <span style="font-family: "Courier New",Courier,monospace;"><b>Post Options</b></span>, <i style="font-family: Arial,Helvetica,sans-serif;">Use <br / > tags</i> is selected for Edit HTML Line Breaks.</li>
<li>When you are editing your post and need to insert a bit of code for the syntax highlighter, switch to the <u><b style="font-family: "Courier New",Courier,monospace;">Edit HTML</b></u><b style="font-family: inherit;"> </b>tab of the editor and insert the following: <pre class="brush:javascript">
<pre class="brush:xml">
<somexml>
Some other xml stuff</somexml>
</pre>
</pre>
Where you substitute "brush:xml" with "brush:[whichever brush you are using]".</li>
</ol>
One weirdness I also noticed is that sometimes it looks likes it's not working, but waiting a few seconds and refreshing, everything is okay again.<br />
<br />
Hopefully this was helpful to someone...and hopefully I haven't been too redundant.Caffiend Froghttp://www.blogger.com/profile/02653710208107242914noreply@blogger.com0