tag:blogger.com,1999:blog-26480735174594348522024-03-13T04:52:24.714+00:00G's BlogGerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.comBlogger272125tag:blogger.com,1999:blog-2648073517459434852.post-63621822348401166352018-11-30T21:04:00.000+00:002018-11-30T21:04:01.913+00:00In JDK 9 (and well 8) and above everything can be a stream.In JDK 8 we finally got to use streams and everything was good apart from the times when the API you used couldn't produce a stream. Then you ended up writing a wrapper class method that allowed you to convert an iterator into a Stream, because you missed streams.<br />
<br />
<pre name="code" class="java">public static <T> Stream<T> asStream(Iterator<T> it) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
Spliterator.IMMUTABLE | Spliterator.ORDERED),false);
}
</pre><br />
Now there are methods to programmatically generate stream in the case of <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html#iterate(T,java.util.function.UnaryOperator)">iterate</a> and <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html#generate(java.util.function.Supplier)">generate</a> but both of these generate an infinite stream whereas in most cases you really wanted to adapt an existing interface into a finite Stream.<br />
<br />
This was resolved nicely in JDK 9 with the introduction of a new form of <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html#iterate(T,java.util.function.Predicate,java.util.function.UnaryOperator)">iterate</a> method that allows you to provide a predicate to signal the end of the stream. <br />
<br />
In the examples below I am going to use a predicate that continues until you get a null entry to the stream, I will leave it up to the reader to come up with more imaginative uses for predicate. In this simple example I am using the getCause method of Throwable to move us along a linked list of errors. Note how little code this would take when compared with a pre stream version.<br />
<br />
<pre name="code" class="java">// Simple linked list
//
Exception e = new Exception("one");
Exception e2 = new Exception("two",e);
Exception e3 = new Exception("three", e2);
Stream.iterate(e3, Objects::nonNull, Throwable::getCause)
// Output the messages in turn
.map(Throwable::getMessage)
.forEach(System.out::println);
</pre><br />
The second example converts a ReferenceQueue into a Stream so that we can easily drain its contents for processing as required. This code is a little bit different because the container is different from the object be worked on, so we provide the seed and the next value using the same method, This returns null when the queue becomes empty.<br />
<br />
<pre name="code" class="java">ReferenceQueue<Thing> queue = new ReferenceQueue<>();
// Make some things and then collect them
WeakReference one = new WeakReference<Thing>(new Thing(), queue);
WeakReference two = new WeakReference<Thing>(new Thing(), queue);
System.gc(); System.gc(); System.gc(); System.gc(); System.gc();
Stream.<Reference<? extends Thing>>iterate(
queue.poll(), Objects::nonNull, v -> queue.poll())
.forEach(System.out::println);
</pre><br />
The third example shows a walk over a Node tree, note the nested stream iterator to work back up the list when we have worked to the end of a leaf.<br />
<br />
<pre name="code" class="java">Node root = doc.getDocumentElement();
Stream.iterate(
root,
Objects::nonNull,
v -> {
if (v.getFirstChild()!=null) {
return v.getFirstChild();
}
if (v.getNextSibling()!=null) {
return v.getNextSibling();
}
return Stream.iterate(v, Objects::nonNull, Node::getParentNode)
.filter(node -> node.getNextSibling()!=null)
.map(Node::getNextSibling).findFirst().orElse(null);
})
.map(Node::getNodeName)
.forEach(System.out::println);
</pre><br />
So with a little bit of mental gymnastics it is possible to transform most legacy APIs into a nice clean Stream, so you can ignore those nasty old fashioned for loops. And if you are stuck in JDK 8 then it is quite easy to put together a similar function using the asStream from before:<br />
<br />
<pre name="code" class="java">public static<T> Stream<T> iterateFinite(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) {
return asStream(new Iterator<>() {
T current = seed;
@Override
public boolean hasNext() {
return hasNext.test(current);
}
@Override
public T next() {
if (current == null) {
throw new NoSuchElementException();
}
try {
return current;
} finally {
current = next.apply(current);
}
}
});
}
</pre><br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-61678653822547508982018-11-27T16:38:00.000+00:002018-11-27T16:38:23.157+00:00await in turn by mistakeI really enjoy working with the new async functions but it is really easy to set up a situation where code that could be running in parallel is force to run in sequence. Consider this simple invocation of a javascript function that takes two values returned from other async functions:<br />
<br />
<pre name="code" class="javascript"> const combination = await combine(await value(1), await value(2));
</pre><br />
The problem here is that unless the JS environment does some optimisation for you, the actions contained in the two called to await are performed in series.<br />
<br />
<pre name="code" class="javascript">function action() {
return new Promise(resolve => {
setTimeout(resolve, 5000)
})
}
async function value(v) {
console.log('started ' + v);
return action('broken ' + v).then(()=> {
console.log("finished " + v);
return "ok " + v
})
}
async function test() {
console.log(await value('1') + " " + await value('2'));
}
test();
</pre><br />
This will result in an output that look something like this, and will take about ten seconds:<br />
<br />
<pre>(index):39 started 1
(index):39 finished 1
(index):37 started 2
(index):39 finished 2
(index):44 ok 1 ok 2
</pre><br />
So there are a number of way to re-write this code in order to ensure that the original processes are all started at the same time, I think the second is the best form, just wish they had put some syntactic sugar so we could do away with Promise.all references.<br />
<br />
<pre name="code" class="javascript">async function test() {
// Worst
const three = value('3');
const four = value('4');
console.log(await three + " " + await four);
// Better
const [five, six] = await Promise.all([value('5'), value('6')];
console.log(five + " " + six));
// Better?
console.log(...await Promise.all([value('7'), value('8')]))
}
test();
</pre><br />
So you would expect a test output to be similar to this, with each block taking about the minimum 5 seconds.<br />
<br />
<pre>(index):37 started 3
(index):37 started 4
(index):39 finished 3
(index):39 finished 4
(index):47 ok 3 ok 4
(index):37 started 5
(index):37 started 6
(index):39 finished 5
(index):39 finished 6
(index):48 ok 5 ok 6
(index):37 started 7
(index):37 started 8
(index):39 finished 7
(index):39 finished 8
(index):48 ok 7 ok 8
</pre><br />
It is really easy to make the same mistake when writing a for loop for example by waiting on each item in turn<br />
<br />
<pre name="code" class="javascript">async function test() {
const list = ['1', '2', '3'];
const result = [];
for (const item of list) {
result.push(await value(item));
}
console.log(result);
}
</pre><br />
For most operation that involve Promise and loop you will normally need map/Promise.all at some point. This version should complete in around the minimum 5 seconds.<br />
<br />
<pre name="code" class="javascript">async function test() {
const list = ['1', '2', '3'];
const result = await Promise.all(list.map(value));
console.log(result);
}
</pre><div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-50491426790901107502018-10-05T13:48:00.000+01:002018-10-05T13:51:12.155+01:00Understanding ordering with JavaScript async methodsSo I challenged someone in a code review to prove that there code that made use of async functions wouldn't be susceptible to a race condition. To that end I came up with a very trivial code example to demonstrate the issue, worth trying to write down the output and line orderings before you read on.<br />
<br />
<pre name="code" class=javascript>let list;
async function clearList () {
list = []; // A
}
async function processList (processList) {
await clearList(); // B
list = list.concat(processList); // C
}
processList([1,2,3]); // D
processList([4,5,6]) // E
.then(() => {
console.dir(list); // F
})
</pre><br />
So the two questions here are what is the output of this code and what order do the lines of code get executed in. Now the point of the code was that it would show that the output is <code>[1,2,3,4,5,6]</code> because of the race condition; but the actual ordering of the execution of the lines of code I had wrong.<br />
<br />
My assumption was that you would not enter the async method directly and instead be queued to be performed on a later clock tick. This gave me an execution flow of <code>D,E,B,B,A,A,C,C,F</code> which I was happy with until my coworker Millan Kuchtiak pointed out I was entirely incorrectly.<br />
<br />
It turns out that at least in Chrome and Safari that code doesn't get transferred queue until you reach the first await call. So actually when you run the code through with a debugger the flow is <code>D,B,A,E,B,A,C,C,F</code>. This make sense from a performance point of view, some async methods might never need the change of context, so just in time async.<br />
<br />
To summarise <b>an async method is synchronous up until the first await</b><div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-65727867062062301162018-08-08T18:01:00.000+01:002018-08-08T18:01:24.499+01:00Trusting a self signed certificate in Oracle Visual Builder CloudWhen you are setting up a development environment you sometimes need to use self signed certificates or a separate developer CA, in order to use this in VBCS you will need to make sure that these certificates are trusted by the kss://system/trust store and have the latest 18.3.3 patches.<br />
<br />
To do this you need to head to <code>/em</code> aka "Fusion Middleware Control" for your instance and navigate to the keystore page for the domain.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRyVstJGQIqFprpI7o8zW4dqbD8C_x2ZoxCqqwqvMxKSjRhm7g8-xf2RLnnWmENdLcL2Cknm-4wjW0HJJ9o3GkqKn9SvfcL981s-eBWIpj-nn0YhSUI-fy9JCQZqhbCAwls9kbB3n4yal/s1600/GotoKeyStore.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRyVstJGQIqFprpI7o8zW4dqbD8C_x2ZoxCqqwqvMxKSjRhm7g8-xf2RLnnWmENdLcL2Cknm-4wjW0HJJ9o3GkqKn9SvfcL981s-eBWIpj-nn0YhSUI-fy9JCQZqhbCAwls9kbB3n4yal/s400/GotoKeyStore.png" width="251" height="400" data-original-width="545" data-original-height="869" /></a></div><br />
<br />
You then need to navigate to the system/trust keystore and select manage:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUEYzYCrQZ8jXb38PblL4Y2LTyoB5jLAxn6xl7AzplydrlB992j3Lec3ZOF6FF6Jb-eIWzZQkTE0ABZKb47-_xEck5xUwb9ntDBY1T57PnzZXuTv2fY2gNY_w51xO-i1Nubm3h2QjiuGHp/s1600/Manage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUEYzYCrQZ8jXb38PblL4Y2LTyoB5jLAxn6xl7AzplydrlB992j3Lec3ZOF6FF6Jb-eIWzZQkTE0ABZKb47-_xEck5xUwb9ntDBY1T57PnzZXuTv2fY2gNY_w51xO-i1Nubm3h2QjiuGHp/s400/Manage.png" width="400" height="219" data-original-width="591" data-original-height="324" /></a></div><br />
<br />
The simply import your certificate, it need to be in .pem format so you might need to do some conversion depending on what you have lying about (Note if you dragged and dropped the certificate from Chrome you can just convert using <code> openssl x509 -inform der -in certificate.cer -out certificate.pem</code>):<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCN0qQStIahClSvNHTpKd5rp2DJBRa8goQ4bgzFBFHbGSuJCFVQo724NAJ7gyjrWUl1KfTrM7V8kxbI34bvNUL-FgYfSnDjbcJbV-BXCiSXcehd8ri_5LhLMpjlDjNgHHKIGNAAEP7t2iS/s1600/Import.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCN0qQStIahClSvNHTpKd5rp2DJBRa8goQ4bgzFBFHbGSuJCFVQo724NAJ7gyjrWUl1KfTrM7V8kxbI34bvNUL-FgYfSnDjbcJbV-BXCiSXcehd8ri_5LhLMpjlDjNgHHKIGNAAEP7t2iS/s400/Import.png" width="400" height="315" data-original-width="669" data-original-height="527" /></a></div><br />
This should now be trusted, you may have to restart the Breeze war in order to see the changes take effect.<br />
<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-24585863402764606792018-01-31T10:35:00.002+00:002018-01-31T10:35:38.937+00:00Quick Debugger Tip, where was that class loaded from.Often when it is Friday afternoon and you want to go home early you come across an intractable class loading issue. You might <a href="/2011/10/few-simple-command-line-operations-on.html">grep your application server home</a>, examine all the domains you can find. (I was looking at weblogic) And still you cannot find out where the class is coming from.<br />
<br />
Now you can use the debugger in your IDE of choice to get hold of the class loader; but in this case the parent class loader had upwards of 300 jar files in it so this was going to be a pain to be sure. So it occurred there was a quicker way, just use the standard method getResource to ask the class loader which jar the file was coming from:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqtlGgrGo0z4n_P4bbdOyQHShjJ2xethCXdfbgW2c6sjOELm2eLfvGAq1tDGYiEkDghdL6o_GerbvnbfKDW9n-uSEFnY5ab9dV-iHN6wrfBijemqD9JrI8xA-F59QYYa7Yd4Zn_R5TS58m/s1600/Screen+Shot+2018-01-31+at+10.19.41.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqtlGgrGo0z4n_P4bbdOyQHShjJ2xethCXdfbgW2c6sjOELm2eLfvGAq1tDGYiEkDghdL6o_GerbvnbfKDW9n-uSEFnY5ab9dV-iHN6wrfBijemqD9JrI8xA-F59QYYa7Yd4Zn_R5TS58m/s1600/Screen+Shot+2018-01-31+at+10.19.41.png" data-original-width="700" data-original-height="610" /></a></div><br />
Turned out someone has installed SOA on this particular weblogic install, and all the relevant files were in a different directory root: this is why my original grep didn't find the jar files.<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-56087401037403790932017-06-15T11:30:00.000+01:002017-06-15T14:47:55.603+01:00Interpreting wpad.dat using jrunscript from JDK 8 to work out the right proxy.In many environments you find that the correct proxy can only be fetched by parsing http://wpad/wpad.dat, which is a pain because it is actually a JavaScript file. Working out the right proxy to call for say a unix environment is a bit of a fiddle particularly if you company is huge and requires different proxies for different countries. JDK 8 to the rescue, as you can run a simple script in the Nashorn environment to get the suggested proxy for one host and use that for everything:<br />
<br />
<pre name="code">jrunscript -e "`curl -o - -s http://wpad/wpad.dat` function isPlainHostName(hostname) { return hostname.indexOf('.')==-1;}; var proxyList = FindProxyForURL('http://github.com','github.com'); var firstProxy = proxyList.split(';')[0].trim(); print('DIRECT'.equals(firstProxy) ? '' : 'http://' + firstProxy.split(' ')[1]);"
</pre><br />
Depending on your local environment you might have to implement one or more functions from the <a href="https://findproxyforurl.com/pac-functions/">list that your wpad.dat</a> expects, in our case I needed to implement isPlainHost.<br />
<br />
The last part of the script just picks the first proxy name, as the function returns a list of PROXY is suggested order. The raw output looks like this:<br />
<br />
<pre name="code">PROXY london.example.com:80; PROXY sf.example.com:80; DIRECT;
</pre><br />
So we just pick the first one with http as the prefix, as some tools such as docker are fussy about this, or returns an empty string if DIRECT is recommended.<br />
<br />
<pre name="code">http://london.example.com:80
</pre><div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-71061501543813378742017-03-14T15:53:00.002+00:002017-03-14T15:53:12.900+00:00The "debugger" reserved word in JavaScriptThis is a handy little tip for cases where you just can't get your debugger to start in the right context or the framework you are using doesn't give you a clear path to know when you file might be loaded. (For example ABCS, or Application Builder Cloud Service, that I am currently working on has this problem)<br />
<br />
In this case just add the debugger statement in your javascript and voila when run in a browser the debugger is popped up.<br />
<br />
<pre name="code" class="javascript">
someCode().then(value => {
debugger;
});
</pre><br />
Always pays to read the reserved word list when learning a new language, you never know what you might find.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-81225190779586885402016-08-15T15:52:00.001+01:002016-08-16T09:27:50.704+01:00What is bound to generic types for method references in java 8, types and exceptionsSo most of the time you are probably aware of method references that either reference instance of static methods directly, and they are useful but not necessarily that interesting.<br />
<br />
<pre name="code" class="java">Integer example = 1;
// We can bind the instance variables, in this case just the return type is bound but there couple be method parameters also
Supplier<String> s = example::toString;
// We can bind to static method, here the generic parameter are the method parameter and return type
Supplier<Long> f = System::currentTimeMillis;
Function<Integer,Integer> f = example::compareTo;
</pre><br />
A less common formulation is to pass in instance methods and find the first generic parameter of of the function to be the type, this allows you to easily pass in a range of actions to operate on a common type:<br />
<br />
<pre name="code" class="java">Function<Integer,String> f = Integer::toString
</pre><br />
For example you can create an equals method that works on a subset of properties using functions mapped to instance methods as in the above example:<br />
<br />
<pre name="code" class="java">public static <T> boolean equals(T one, T two, Function<? super T, ?>... accessors) {
if (one == two) {
return true;
} else if (one==null || two==null) {
return false;
}
return Stream.of(accessors).allMatch(accessor ->
Objects.equals(accessor.apply(one),accessor.apply(two)));
}
if (equals(one, two, Thing::getName, Thing:getOtherProperty)) ...;
</pre><br />
Finally you can also bind the exception thrown from the method to one of the generic parameters. (Here I am using ThrowingException and ThrowingSupplier my home brew interfaces that are like there namesakes but have a generic parameter E for the exception thrown) This allows you to make you "closure" transparent to exceptions. This is more useful in a lot of cases when compared to the Stream throw nothing and "throws Exception" extremes. <br />
<br />
<pre name="code" class="java">ThrowingException<String,Integer,NumberFormatException> te = Integer::parseInt;
</pre><br />
You can write funky closure methods that will throw different exceptions based on the passed in method reference does, no more catch (Exception).<br />
<br />
<pre name="code" class="java">public static <T, E extends Exception> T withCC(Class<?> contextClass,
ThrowingSupplier<T,E> action) throws E {
Thread t = Thread.current();
ClassLoader cl = t.getContextClassLoader();
try {
t.setContextClassLoader(contextClass.getClassLoader());
return action.get();
} finally {
s.setContextClassLoader(cl);
}
}
// Throws IOException, complier knows that this method call throws IOException
String value = withCC(Example.class, () -> {
...
... new FileOutpuStream(file); ...
...
});
// Throws another exception, complier knows that this method call throws RMIExeption
String value = withCC(Example.class, () -> {
...
throw new RMIException();
});
</pre><br />
Once you understand the last two, method reference start to become far more interesting.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-84786950873026293102016-06-02T15:30:00.000+01:002016-06-02T15:30:01.208+01:00Getting a name for someone to connect back to your server.When doing test automation it is often the case you need to know the name of the current machine in order to prompt another machine to connect to it, particularly if you are running your tests in parallel. This week I was trying to get the server under test to connect back to a WireMock server running on the slave test machine.<br />
<br />
The standard response on stack overflow is to use the following pattern to get a network address. In my version here if we can't resolve the name then we are assuming we are running on a developers laptop on VPN so all the tests are run on the same machine. (Hence localhost)<br />
<br />
<pre name="code" class="java">String hostName = "localhost";
try {
InetAddress addr = InetAddress.getLocalHost();
String suggestedName = addr.getCanonicalHostName();
// Rough test for IP address, if IP address assume a local lookup
// on VPN
if (!suggestedName.matches("(\\d{1,3}\\.?){4}") && !suggestedName.contains(":")) {
hostName = suggestedName;
}
} catch (UnknownHostException ex) {
}
System.out.println(hostName);
</pre><br />
The problem comes is that we have to trust the local machine settings, for example /etc/hostname, which can result in a network name that is not accessible from another machine. To counter this I wrote the following code to work over the available network interfaces to find a remotely addressable network address name that can be used to talk back to this machine. (I could use an IP address but they are harder to remember, particularly as we are moving towards IPv6)<br />
<br />
<pre name="code" class="java">String hostName = stream(wrap(NetworkInterface::getNetworkInterfaces).get())
// Only alllow interfaces that are functioning
.filter(wrap(NetworkInterface::isUp))
// Flat map to any bound addresses
.flatMap(n -> stream(n.getInetAddresses()))
// Fiter out any local addresses
.filter(ia -> !ia.isAnyLocalAddress() && !ia.isLinkLocalAddress() && !ia.isLoopbackAddress())
// Map to a name
.map(InetAddress::getCanonicalHostName)
// Ignore if we just got an IP back
.filter(suggestedName -> !suggestedName.matches("(\\d{1,3}\\.?){4}")
&& !suggestedName.contains(":"))
.findFirst()
// In my case default to localhost
.orElse("localhost");
System.out.println(hostName);
</pre><br />
You might notice there a are a few support methods being used in there to tidy up the code, here are the required support methods if you are interested.<br />
<br />
<pre name="code" class="java">@FunctionalInterface
public interface ThrowingPredicate<T, E extends Exception>{
boolean test(T t) throws E;
}
@FunctionalInterface
public interface ThrowingSupplier<T, E extends Exception>{
T get() throws E;
}
public static <T, E extends Exception> Predicate<T> wrap(ThrowingPredicate<T, E> th) {
return t -> {
try {
return th.test(t);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
public static <T, E extends Exception> Supplier<T> wrap(ThrowingSupplier<T, E> th) {
return () -> {
try {
return th.get();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
// http://stackoverflow.com/a/23276455
public static <T> Stream<T> stream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<T>() {
public T next() {
return e.nextElement();
}
public boolean hasNext() {
return e.hasMoreElements();
}
},
Spliterator.ORDERED), false);
}
</pre><div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-60717987043071728282016-04-07T16:04:00.001+01:002016-04-07T21:26:56.572+01:00Converting string configuration properties to other types, with a bit of Optional.Somedays you come across some code and think that's pretty, why didn't I think of that? So my long time colleague Mark Warner has a nice twist on the standard name/value store pattern using method references to deal with converting from a String.<br />
<br />
<pre name="code" class="java">int size = store.getProperty("cache.limit", 500, Integer::parseInt);
boolean enabled = store.getProperty("cache.enabled", true, Boolean::getBoolean);
</pre><br />
I took his example and refactored it slightly to return Optional, and I ended up with the following:<br />
<br />
<pre name="code" class="java">public Optional<String> getProperty(
String propertyName) {
return Optional.ofNullable(map.get(propertyName));
}
public <T> Optional<T> getProperty(
String propertyName,
ThrowingFunction<String,? extends T,? extends Exception> func ) {
return getProperty(propertyName).map(val -> {
try {
return func.apply( val );
} catch ( Exception e ) {
LOGGER.severe( () -> "Invalid property transform, will default " + e.getMessage() );
return null;
}
});
}
</pre><br />
This means that the default value ends up being provided by the Optional which is a nice application of OAOO.<br />
<br />
<pre name="code" class="java">int size = store.getProperty("cache.limit", Integer::parseInt).orElse(500);
boolean enabled = store.getProperty("cache.enabled", Boolean::getBoolean).orElse(true);
</pre><br />
I think this is even tidier; but it does depend on who you feel about using Optionals.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-12421808593806279622016-03-10T10:20:00.001+00:002016-03-14T11:00:11.963+00:00Lambda of Lambda, if/else from an OptionalSo I got frustrated with two limitations of the Optional interface in JDK 8. The first problem is that there is no obvious way to perform an else operation in a block as there is only a <code>isPresent</code> method unless you are using an old school if statement. The second problem is of course the old chestnut that even if you could do that the methods would not be able to throw a checked exception. (Yes you can wrap with a RuntimeException but it is not the prettiest.)<br />
<br />
The workaround I found was to use the map function as the success case and the orElseGet to return the failure case. In both branches the code returns an instance of ThrowingRunnable by having a lambda return a lambda. The <code>run()</code> is then called at the end and it can throw any exception it wants to.<br />
<br />
<pre name="code" class="java">@FunctionalInterface
public interface ThrowingRunnable<E extends Throwable> {
public void run() throws E;
}
Optional<Credential> credential = ....
credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
PasswordWrapper pw = auth.getToken();
... // something that might throw an IOException
}).orElseGet(() -> () -> {
response.setStatus(401);
LOGGER.log(Level.INFO, "credential is not found");
}
).run();
</pre><br />
This is possibly excessive for this particular use case; but I can see this technique being useful elsewhere and it is worth knowing what it looks like so it is not a surprise in others code.<br />
<br />
<b>Update 14th March 2016:</b> Thanks to <a href="https://dzone.com/users/1239605/Maldivia.html">Michael Rasmussen</a> on the DZone version of this article he noted I could use <code>orElse</code> rather than <code>orElseGet</code> to remove the second double lambda.<br />
<br />
<pre name="code" class="java">credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
PasswordWrapper pw = auth.getToken();
... // something that might throw an IOException
}).orElse(() -> {
response.setStatus(401);
LOGGER.log(Level.INFO, "credential is not found");
}
).run();
</pre><br />
<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-57724332922810464862016-03-02T16:52:00.000+00:002016-03-02T16:52:43.710+00:00Getting hold of an un-used port when writing a testA really quick post today, I was writing a unit test that needed to put up a temporary JAX-RS resource in order to test something very specific with out the need of a large testing framework. Unfortunately the code I was using didn't know about replacing zero with a random allocated port so I had to do something different. The nice tidy code that does this looks like the following:<br />
<br />
<pre name="code" class="java">try(ServerSocket ss = new ServerSocket(0)) {
freePort = ss.getLocalPort();
}
server = createServerWithPort(freePort);
</pre><br />
But of course there is a race condition here as there could be another process on the machine running the exact same code that gets lucky with its time on the CPU - note the API I was using couldn't use the ServerSocket directly so there is a gap where the port is not tied up. So to rule out the one in a million failure chance, which always comes on a Friday at 5pm, we need to wrap this code in a loop.<br />
<br />
<pre name="code" class="java">while(server==null) {
try(ServerSocket ss = new ServerSocket(0)) {
freePort = ss.getLocalPort();
}
server = createServerWithPort(freePort);
}
</pre><br />
This may seem extreme; but if you are running some kind of CI system like Hudson or Jenkins it is not unusual to be running multiple executors on the same machine. You might have two developers running preflights at the same time causing an annoying intermittent failure as described above.<br />
<br />
Finally a version using a JDK 8 stream with a helper method to convert the IOException from ServerSocket into a RuntimeException. Some would argue this is less readable; but I find it more explicit.<br />
<br />
<pre name="code" class="java">server = Stream.generate(convertException(() -> {
try(ServerSocket ss = new ServerSocket(0)) {
return ss.getLocalPort();
}
})).map(TestClass::createServerWithPort)
.filter(Objects::nonNull)
.findFirst().get();
</pre><div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-45312110185814199422016-01-20T15:29:00.000+00:002016-01-27T10:14:39.582+00:00Removing multiple items from a JavaScript array, no for loopsSo I was reviewing some code today that was using two for loops to remove elements from a JavaScript array, I won't relate the code here but I figured there as got to be a nicer way. So the first guess is to make use of the filter method; but that creates a new array which might be problem if the array is large but not if it is fairly small or not called very often.<br />
<br />
<pre name="code" class="javascript">providers = providers.filter(function(provider) {
return provider.age > 35
}
</pre><br />
For performance or API reasons you might want to perform an in place removal using splice, so you can simple map the values to indexes you want to remove, reverse the order then perform a sequence of splice operations:<br />
<br />
<pre name="code" class="javascript">providers.map(function(provider, index) {
return provider.age > 35 ? index : -1;
}).filter(function(index) {
return index >= 0;
}).reverse().forEach(function(index) {
providers.splice(index,1);
});
</pre><br />
You can play with this code in this <a href="https://jsfiddle.net/kingsfleet/2ua0062b/">jsfiddle</a>.<br />
<br />
<b>Update 21 Jan 20125:</b> The hazard of doing full stack development is that it is easy to accidentally duck type between languages whilst forgetting the impact. In Java the equivalent streaming code using map just returns another lazy step in the stream whereas in JavaScript you end up creating a new array of the same size as the original. This removes the performance improvement over the first example if you have lots of data. This is simple too fix though as you can use the reduce function to just create an array and populate it using the reduce operation:<br />
<br />
<pre name="code" class="javascript">providers.reduce(function(list, provider, index) {
if (provider.age> 35) list.push(index);
return list;
}, []).reverse().forEach(function(index) {
providers.splice(index,1);
});
</pre><br />
Here is the updated <a href="https://jsfiddle.net/kingsfleet/nqv8jdLL/1/">fiddle</a>. I guess at some point I am going to have to benchmark these variants to see which is best; but that is for a less busy day.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-22507148458489963342016-01-12T15:15:00.001+00:002016-01-12T16:01:08.982+00:00Beware of slightly different behaviour between ConcurrentMap and ConcurrentHashMap for computeIfAbsentSo I was refactoring some code to use non-locking collection classes and I noticed the this significant different between <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentMap.html#computeIfAbsent-K-java.util.function.Function-">ConcurrentMap.computeIfAbsent</a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent-K-java.util.function.Function-">ConcurrentHashMap.computeIfAbsent</a>. They key different is that for the former default implementing the mapping function can be called many times for a particular key where as for the concrete implementation it will be called only once. This will likely affect whether the code in the function needs to be thread safe or not.<br />
<br />
Right okay so armed with that you know that any collection that implements just ConcurrentMap will inherit this behaviour, further to that I found in particular guava would return a different implementation depending on the passed on parameters:<br />
<br />
<pre name="code" class="java">ConcurrentMap map1 = new MapMaker().makeMap();
System.out.println(map1.getClass());
ConcurrentMap map2 = new MapMaker().weakKeys().makeMap();
System.out.println(map2.getClass());
....
class java.util.concurrent.ConcurrentHashMap
class com.google.common.collect.MapMakerInternalMap
</pre><br />
MapMakerInternalMap doesn't override computerIfAbsent therefore the behaviour of this function will be significantly different depending on the parameters to pass into the maker, something that might be apparent from the get go.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-20041944368359460552015-11-25T15:54:00.000+00:002015-11-25T15:54:54.981+00:00A very simple implementation of Suite to make it easy to run across a bunch of test machines at the same time.So I was presented with a large suite that I need to distribute amongst an arbitrary number of Hudson slaves. Now my first guess would be to hand balance this into N sub suites; but that would require on-going work and would need to change depending on the number of nodes. (We have a target of 30 minutes to run all tests in parallel which is going to take some machines)<br />
<br />
<pre name="code" class="java">@RunWith(Suite.class)
@Suite.SuiteClasses({
TableCRUD.class,
TableCRUDChild.class,
TableFilterSort.class,
TableDefaultQuery.class,
TableActions.class,
....
})
public class DevSuite {
}
</pre><br />
So the quickest way I found to do this was to write different version of Suite that allocated the tests to different bins. This implementation doesn't ensure properly balanced bins as it is biased towards keeping the order stable and consistent which is useful for comparing tests results split into multiple jobs.<br />
<br />
<pre name="code" class="java">
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.junit.runner.Runner;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
/**
* Try to proportion a suites tests into "SPLIT" number of equals sections and
* then just run "SECTION" rather than all of the tests. Defined by
* "SplitSuite.split" and "SplitSuite.section" respectively
*/
public class SplitSuite
extends Suite {
private static int SECTIONS
= Integer.getInteger("SplitSuite.split", -1);
private static int SECTION
= Integer.getInteger("SplitSuite.section", -1);
public SplitSuite(RunnerBuilder builder, Class<?>[] classes) throws InitializationError {
super(builder, classes);
}
public SplitSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {
super(klass, builder);
}
public List<Runner> getChildren() {
if (SECTIONS < 0) {
return super.getChildren();
} else if (SECTIONS == 0) {
throw new IllegalArgumentException("SplitSuite.split needs to be a positive integer, it cannot be zero. A negative valid will disable this feature.");
} else if (SECTION >= SECTIONS) {
throw new IllegalArgumentException("SplitSuite.section parameter " + SECTION + " needs to be less than SplitSuite.split " + SECTIONS);
}
final Map<Integer, List<Runner>> collect = originalList.stream().collect(
assignToGroups(SECTIONS, Runner::testCount, originalList));
return collect.get(SECTION);
}
/**
* Assigns object to buckets, moving to the next when filled, whilst preserving
* the original order.
* @param <Type> The type that has some kind of size property
* @param sections The number of sections to split the code across
* @param sizer A function to return the size of the given object
* @param originalList The original list to provide a base line size
* @return A map that contains an order list of sections
*/
public static <Type> Collector<Type, ?, Map<Integer, List<Type>>> assignToGroups(
int sections,
final ToIntFunction<Type> sizer,
Collection<Type> originalList) {
// Get length
int count = originalList.stream().collect(Collectors.summingInt(sizer));
// Workout section length
int sectionLength = count / sections;
Function<Type, Integer> grouping = new Function<Type, Integer>() {
int counter = 0;
@Override
public Integer apply(Type t) {
int section = Math.min(counter / sectionLength, sections - 1);
counter += sizer.applyAsInt(t);
return section;
}
};
return Collectors.groupingBy(grouping, TreeMap::new, Collectors.toList());
}
}
</pre><br />
So a quick change to the suite class....<br />
<br />
<pre name="code" class="java">@RunWith(SplitSuite.class)
@Suite.SuiteClasses({
TableCRUD.class,
TableCRUDChild.class,
TableFilterSort.class,
TableDefaultQuery.class,
TableActions.class,
....
})
public class DevSuite {
}
</pre><br />
Now the actual test step looks like this, note that this is running under hudson but you should be able to achieve something similar on the CI server of your choice. In order to make my life easier I derive the section number from the job name for so 3 sections I have ..._0 ..._1 and ..._2. In hudson the later jobs all cascade from the the first sharing all properties which makes maintenance a lot easier.<br />
<br />
<pre name="code">
java ... -DSplitSuite.sections=${SECTIONS} -DSplitSuite.section=`echo ${JOB_NAME} | sed -e s/.*_//` ...
</pre><br />
And it appears to work, obviously the algorithm to split the suites could be better to produce more balanced results; but that is an effort for another day.....<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-82620938840699790322015-07-31T16:32:00.001+01:002017-11-24T13:53:09.440+00:00Creating a shared library for Jersey 2.19 to use with Weblogic 12.1.3Weblogic server comes with a shared library so you can deploy JAX-RS 2.0 applications; but is limited to Jersey version 2.5.1 and the instructions for changing this are not entirely <a href="https://docs.oracle.com/middleware/1213/wls/RESTF/use-jersey20-ri.htm#RESTF302">obvious or straightforward</a>. I have recently joined a new team at Oracle and one of the first things I did was to look at upgrading the dependent libraries. Now I have talked to the Jersey team and they don't support this combination; but it maybe useful enough to get you out of a bind until the next version of Weblogic is released.<br />
<br />
I am going to do this using Maven because it means all the packaging and downloading is done for you. The basic structure of the project is as follows:<br />
<br />
<pre name="code">|-pom.xml
|-src
| |-main
| | |-java
| | |-resources
| | | |-META-INF
| | | | |-MANIFEST.MF
| | |-webapp
| | | |-WEB-INF
| | | | |-web.xml
| | | | |-weblogic.xml
</pre><br />
I just generated a vanilla Maven project using Netbeans and then added in the Jersey dependencies I needed, it is likely this file could be cut down a little bit more with some determination. But it worked well enough for me:<br />
<br />
<pre name="code" class="xml"><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>JerseyLibrary</artifactId>
<version>2.19</version>
<packaging>war</packaging>
<name>Jersey Library</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jersey.version>2.19</jersey.version>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project></pre><br />
The next most important file in the MANIFEST.MF file, this tells Weblogic when you try to deploy the .war that this is a library and also contains the versions it supplies:<br />
<br />
<pre name="code">Specification-Title: Weblogic JAX-RS 2.0
Specification-Version: 2.0
Implementation-Title: Weblogic JAX-RS 2.0 Reference Implementation
Implementation-Version: 2.19
Extension-Name: jax-rs
</pre><br />
Finally, you have to include a weblogic.xml file to tell the server that some classes you need to take from here rather than the server class loader. I got the basis of this from the file that comes with the 2.5.1 shares library that ships with 12.1.3 and then added a few more lines to take in account how the code has moved on. Depending on what your code is doing you may have to add a few more.<br />
<br />
<pre name="code" class="xml"><?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app
xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<container-descriptor>
<prefer-application-packages>
<!-- apis -->
<package-name>javax.ws.rs.*</package-name>
<!-- guava -->
<package-name>com.google.common.*</package-name>
<!-- jersey providers -->
<package-name>com.sun.jersey.*</package-name>
<package-name>org.glassfish.jersey.*</package-name>
<package-name>jersey.repackaged.*</package-name>
<!-- hk2 -->
<package-name>org.jvnet.hk2.*</package-name>
<package-name>org.jvnet.hk2.tiger_types.*</package-name>
<package-name>org.glassfish.hk2.*</package-name>
<package-name>javassist.*</package-name>
<!-- media providers -->
<package-name>org.eclipse.persistence.jaxb.rs.*</package-name>
<package-name>org.codehaus.jackson.jaxrs.*</package-name>
<!-- wls -->
<package-name>weblogic.jaxrs.api.client.*</package-name>
<package-name>weblogic.jaxrs.internal.api.client.*</package-name>
<package-name>weblogic.jaxrs.dispatch.*</package-name>
<package-name>weblogic.jaxrs.monitoring.util.*</package-name>
</prefer-application-packages>
</container-descriptor>
</weblogic-web-app>
</pre><br />
Now all this needs is a quick <code>mvn install</code> and in the target directory there will be a nice complete shared library called JerseyLibrary-2.19.war that you can deploy in the normal way. Remember of course to update the library entries for the .war that is going to depend on this to have the right versions in it so it does pick up the 2.5.1 version.<br />
<br />
<b>Update Nov 2018:</b>I tried this with Jersey 2.21.1 into WLS 12.1.2 but found that because of the need to create proxies for injection I wasn't able to get my code to work because of a <a href="https://github.com/javaee/hk2/issues/376">hk2 issue</a>. You can create a local copy of this class in order to workaround the problem; but this is starting to get further and further from a supportable solution.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-35388699303400903732015-03-09T11:50:00.002+00:002015-03-09T11:50:30.481+00:00Quick and dirty test for thread leakage in javaI was looking at a bit of code was leaking class loaders when deployed to tomcat - so I wanted to quick rule out that a background Thread was holding onto the loader. Pain by eye, it is quite easy with a few unix commands to process the stack trace, filter for the lines that contain the thread name, filter for just the thread names and sort:<br />
<pre name="code">sudo -u tomcat jstack 1853 | grep " prio=" | sed -e 's/"\(.*\)".*/\1/' | sort
</pre>Once this is done it is a simple matter to pipe the output to a file, say /tmp/before.threads, then run the deploy task a small prime number of times in order to create a clear signal, and then compare with the original thread list<br />
<pre name="code">[gdavison ~]$ diff /tmp/before.threads /tmp/after.threads
26a27
> RMI TCP Connection(11)-127.0.0.1
[gdavison ~]$
</pre>As with any server there will be a lot going on, in this case I saw a spurious RMI thread we can probably ignore, but if there was any application specific thread leakage the problem should repeat a number of times that is cleanly divisible with the prime number you picked before, for example where the prime is three with an example issue:<br />
<pre name="code">[gdavison@slc01htu ~]$ diff /tmp/before.threads /tmp/after.threads
8a9,11
> Problem Thread
> Problem Thread
> Problem Thread
26a30
> RMI TCP Connection(11)-127.0.0.1
[gdavison ~]$
</pre><br />
As I say quick and dirty; but might be worth writing down for later use.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-76974058245125134922015-02-12T12:29:00.000+00:002015-02-12T12:29:15.701+00:00How long did I sleep last night: using Cordova, HealthKit, and JavaScript, and a handful of PromisesNow that we can know how much <a href="/2015/02/hows-many-steps-did-i-walk-yesterday.html">activity I did yesterday</a>, we can look at whether I am getting enough sleep.<br />
<br />
A quick look at the <a href="https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Framework/index.html">Apple documentation</a> lets us see that <code> HKCategoryTypeIdentifierSleepAnalysis</code> is the right measure to be using. This is a subtype of <code>SampleType</code> so we can use the querySampleType function.<br />
<br />
First of all here is the same boilerplate code, with the minor modification to allow for access to the sleep data rather than the step data we used before. You could of course combine the two.<br />
<br />
<pre name="code" class="javascript">var wearable = {
avaliable: _.once(function() {
return new Promise(function(resolve, reject) {
if (window.plugins.healthkit) {
window.plugins.healthkit.available(
function() {
console.log("Healthkit is avaliable");
resolve(true);
},
function() {
console.log("Healthkit is not avaliable");
reject(Error(false));
}
);
} else {
reject(Error("HealthKit Not Available"));
}
});
}),
getHealthKit : _.once(function() {
return wearable.avaliable().then(function() {
return new Promise(function(resolve, reject) {
window.plugins.healthkit.requestAuthorization(
{
'readTypes': ['HKCategoryTypeIdentifierSleepAnalysis'],
'writeTypes': []
},
function() {
console.log("HealthKit authorisation accepted");
resolve(window.plugins.healthkit);
},
function() {
reject(Error("HealthKit authorisation rejected"));
});
});
});
}),
...
}
</pre><br />
Then it is s simple matter of querying HeathKit with a useful date range. Note I use <code>limit</code> and <code>ascending</code> to access the last data point - it is possible that different tools will report multiple entires for a single night. (In particular new parents) I need to do a little bit more investigation here.<br />
<br />
<pre name="code" class="javascript">wearable = {
...
querySleep: function() {
wearable.getHealthKit().then(function(healthkit) {
var startDate = moment().subtract('d', 1).toDate();
healthkit.querySampleType({
'startDate': startDate,
'endDate': moment().toDate(),
'sampleType': "HKCategoryTypeIdentifierSleepAnalysis",
'ascending': "NO",
'limit': 1
},
function(value) {
console.log("Success for runing sleep query");
// Debug output for the momment
value.forEach(function(next) {
console.dir(next);
var measure = next.value === 1 ? "Sleeping" : "In Bed";
var minutesSleep = moment(next.endDate).diff(next.startDate, "minutes");
var hoursSleep = moment(next.endDate).diff(next.startDate, "hours");
console.log("Entry got " + minutesSleep + " minutes " + measure);
console.log("Entry got " + hoursSleep + " hours " + measure);
});
// Use data in some way
});
}
}
},
}
</pre><br />
<br />
Finally it would be really useful to be able to be told when data is added to HealthKit by another app for example the client app for a wearable. You can do this using the monitorSampleType function. Ideally this would code would then use something called an anchored query so you only access the most recently added data; but I haven't had time to implement this yet so we simply call querySleep().<br />
<br />
Now making sure you app wakes up in the background to receive this data is a whole other blog....<br />
<br />
<pre name="code" class="javascript">var wearable = {
...
monitorSleep: _.once(function() {
console.log("Starting to monitor sleep");
wearable.getHealthKit().then(function(healthkit) {
healthkit.monitorSampleType({
'sampleType': "HKCategoryTypeIdentifierSleepAnalysis"
},
_.debounce(function(value) {
console.log("Sleep data has been updated, lets see if anything interesting has been added");
wearable.querySleep();
}, 2000),
function() {
console.log("Failed to monitor sample data");
console.dir(arguments);
});
});
})
}
</pre><br />
<br />
<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-33595212762606146342015-02-10T16:47:00.001+00:002015-02-11T16:15:43.183+00:00Per client cookie handling with JerseyA lot of REST services will use cookies as part of the authentication / authorisation scheme. This is a problem because by default the old Jersey client will use the singleton <a href="http://docs.oracle.com/javase/7/docs/api/java/net/CookieHandler.html#getDefault()">CookieHandler.getDefault</a> which is most cases will be null and if not null will not likely work in a multithreaded server environment. (This is because in the background the default Jersey client will use URL.openConnection)<br />
<br />
Now you can work around this by using the Apache HTTP Client adapter for Jersey; but this is not always available. So if you want to use the Jersey client with cookies in a server environment you need to do a little bit of reflection to ensure you use your own private cookie jar.<br />
<br />
<pre name="code" class="java">final CookieHandler ch = new CookieManager();
Client client = new Client(new URLConnectionClientHandler(
new HttpURLConnectionFactory() {
@Override
public HttpURLConnection getHttpURLConnection(URL uRL) throws IOException {
HttpURLConnection connect = (HttpURLConnection) uRL.openConnection();
try {
Object toModify = connect;
if (!(toModify instanceof sun.net.www.protocol.http.HttpURLConnection)) {
Field delegateField = connect.getClass().getDeclaredField("delegate");
delegateField.setAccessible(true);
toModify = MethodHandles.lookup().unreflectGetter(delegateField)
.bindTo(toModify).invoke();
}
Field cookieField = sun.net.www.protocol.http.HttpURLConnection.class.getDeclaredField("cookieHandler");
cookieField.setAccessible(true);
MethodHandle mh = MethodHandles.lookup().unreflectSetter(cookieField);
mh.bindTo(toModify).invoke(ch);
} catch (Throwable e) {
e.printStackTrace();
}
return connect;
}
}));
</pre><br />
This will only work if your environment is using the internal implementation of <code>sun.net.www.protocol.http.HttpURLConnection</code> that comes with the JDK. This appears to be the case for modern versions of WLS.<br />
<br />
For JAX-RS 2.0 you can do a similar change using Jersey 2.x specific <a href="https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/client/ClientConfig.html#connectorProvider(org.glassfish.jersey.client.spi.ConnectorProvider)">ClientConfig class</a> and <a href="https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/client/HttpUrlConnectorProvider.html">HttpUrlConnectorProvider</a>.<br />
<br />
<pre name="code" class="java">final CookieHandler ch = new CookieManager();
Client client =
ClientBuilder.newClient(new ClientConfig().connectorProvider(new HttpUrlConnectorProvider().connectionFactory(new HttpUrlConnectorProvider.ConnectionFactory() {
@Override
public HttpURLConnection getConnection(URL uRL) throws IOException {
HttpURLConnection connect = (HttpURLConnection) uRL.openConnection();
try {
Object toModify = connect;
if (!(toModify instanceof sun.net.www.protocol.http.HttpURLConnection)) {
Field delegateField = connect.getClass().getDeclaredField("delegate");
delegateField.setAccessible(true);
toModify = MethodHandles.lookup().unreflectGetter(delegateField)
.bindTo(toModify).invoke();
}
Field cookieField = sun.net.www.protocol.http.HttpURLConnection.class.getDeclaredField("cookieHandler");
cookieField.setAccessible(true);
MethodHandle mh = MethodHandles.lookup().unreflectSetter(cookieField);
mh.bindTo(toModify).invoke(ch);
} catch (Throwable e) {
e.printStackTrace();
}
return connect;
}
})));
</pre><br />
<br />
<b>Update 11th Feb 2015:</b> It seems in some cases, in particular using https, I have seen the HttpURLConnection wrapped in another class, to work around this just use reflection to access the value of the delegate field. I have updated the code examples to reflect this issue.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-82490935796411843452015-02-01T10:10:00.000+00:002015-02-10T11:14:21.553+00:00How many steps did I walk yesterday: using Cordova, HealthKit, and JavaScript, and a handful of PromisesAs people who know me might know I have been playing around with various wearables for some years now, starting with a Nike Fuel Band, and also trying out products from Misfit and UP along the way. I have mostly just watched with interest as my exercise levels, and indeed sleep now we have a little one in the house, has gone up and down over time. <br />
<br />
More recently with the arrival of HealthKit there comes a standard method of accessing this information from multiple products on the iPhone, I needed to brush up on my JavaScript for work so I decided to have a play in <a href="http://cordova.apache.org">Cordova</a> to build something in my spare time. One of the cool things about that Cordova community when compared to other app development frameworks is the large and healthy plugin community - and quick google and I found what I needed to support HealthKit <a href="https://github.com/Telerik-Verified-Plugins/HealthKit">HealthKit</a>. This took only a small amount of <a href="https://github.com/Telerik-Verified-Plugins/HealthKit/commit/14c0393aa2965bcf62c612528bb27eff6aa5ba29">patching</a> from me to get at the information I wanted. In this blog I will just look at number of steps per day as a proxy for activity.<br />
<br />
I am going to assume the rest of the Cordova App is in place and start with a simple wearable object which exposes a promise that allows you to check whether HealthKit is available on this platform, you might have iOS 8 but HealthKit is iPhone only. Remember that most of Cordova is interacting with a bunch of asynchronous native systems so you have to make sure you consider this as you work with it. Hence the liberal use of <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">promises</a>. (If you are wanting to <a href="http://caniuse.com/#feat=promises">support < iOS 8</a> then you will need to use a different promise library / shim) In this case I am also using the <a href="http://underscorejs.org">underscorejs</a> library to create a promise who's result won't be calculated until it is invoked for the first time.<br />
<br />
<pre name="code" class="javascript">var wearable = {
avaliable: _.once(function() {
return new Promise(function(resolve, reject) {
if (window.plugins.healthkit) {
window.plugins.healthkit.available(
function() {
console.log("Healthkit is avaliable");
resolve(true);
},
function() {
console.log("Healthkit is not avaliable");
reject(Error(false));
}
);
} else {
reject(Error("HealthKit Not Available"));
}
});
}),
...
}
</pre><br />
The next stage of the code, once you are sure that the system is available, is to get verify that you can access the data you want to access. Now Apple is clear in <a href="https://developer.apple.com/healthkit/">there developer guide</a> that you should only request the data you might want to access once. So no asking for step data one time then heath rate data in a different part of the UI. The Cordova HealthKit Plugin will just return with a success if those values are already authorised, so we will use another promise as a gateway to actually working with the data to make one consistent entry point for authorisation.<br />
<br />
<pre name="code" class="javascript">var wearable = {
...
getHealthKit : _.once(function() {
return wearable.avaliable().then(function() {
return new Promise(function(resolve, reject) {
window.plugins.healthkit.requestAuthorization(
{
'readTypes': ['HKQuantityTypeIdentifierStepCount'],
'writeTypes': []
},
function() {
console.log("HealthKit authorisation accepted");
resolve(window.plugins.healthkit);
},
function() {
reject(Error("HealthKit authorisation rejected"));
});
});
});
}),
...
}
</pre><br />
Finally now we have all the ground work in place, lets put in place a simple method to work out how many steps were recorded yesterday. I am then using special function called sumQuantityType that performs some rather clever statistical leg work for you. Consider if you have a iPhone 6 along with step monitoring wrist band of some kind like a Apple Watch, in HealthKit you will have two lots of data that inconsistently overlaps. HealthKit provides methods to deal with this, more information can be found in the <a href="https://developer.apple.com/videos/wwdc/2014/?id=203">WWDC presentation from 2014</a>, but basically it works out for each time segment which data source(s) to use to get the value for the time range requested.<br />
<br />
<pre name="code" class="javascript">var wearable = {
...
querySteps : function() {
return wearable.getHealthKit().then(function (healthkit)
{
return new Promise(function(resolve, reject) {
var m = moment().startOf('day');
var endDate = m.toDate();
var startDate = moment(m).subtract('d', 1).toDate();
healthkit.sumQuantityType({
'startDate': startDate,
'endDate': endDate,
'sampleType': "HKQuantityTypeIdentifierStepCount"
},
function(value)
{
resolve(value)
},
function()
{
reject(Error("Problem queuing steps"));
});
});
}
}
</pre><br />
Now we have this object, we can access the data and show it to the user. Note that the promise objects chain so the catch function will tell you if something went wrong at any stage of the process, if you had tried to wire this up with event handlers you would have had an ungodly mess of code and callbacks.<br />
<br />
<pre name="code" class="javascript">wearable.querySteps()
.then(function(value){
console.log("Number of steps " + value);
... update UI
})
.catch(function (error) {
... update UI
};
</pre><br />
This is of course just the start, there is a lot more interesting stuff you can get from this API; but that is for another day. I like HealthKit because unlike GoogleFit all your health data is stored locally by default. There is a lot of potential here for doing interesting stuff.<br />
<br />
Finally a quick shout out of <a href="https://github.com/EddyVerbruggen">Eddy Verbruggen</a> who created <a href="https://github.com/Telerik-Verified-Plugins/HealthKit">HealthKit plugin</a> along with a whole host of other interesting libraries.<br />
<br />
I am going to walk around for a bit now, gotta meet those targets. :-)<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-6542452626351899012014-11-17T14:47:00.000+00:002014-11-17T14:47:21.599+00:00But that's impossible, or finding out that the JIT has broken your code.Every now and then you look at some code and think that it cannot be possibly be wrong. Once you have ruled out a simple programmer screw up / enemy action in code (Make sure you read Java Puzzlers or similar) or a concurrency issue (Read Java Concurrency or go on <a href="http://www.javaspecialists.eu/courses/concurrency.jsp">Dr Heniz excellent course</a>) you should sit back and take a few days and then starting thinking about whether the JDK is indeed out to get you. I haven't seen one in the wild in my 18 odd years as a Java programmer so it kinda took me by surprise.<br />
<br />
If you are running against JDK 8 in a large scale Swing application you might eventually see the following exception, lots of lots of times. (Unless you forgot the lesson learned in my <a href="/2014/11/missing-stack-traces-for-repeated.html">previous blog</a> in your logging code, in which case you might see lots of ArrayOfOutBoundsException)<br />
<br />
<pre name="code" class="java">Caused by: java.lang.NullPointerException
at javax.swing.text.GlyphView.getBreakSpot(GlyphView.java:799)
at javax.swing.text.GlyphView.getBreakWeight(GlyphView.java:724)
at javax.swing.text.FlowView$LogicalView.getPreferredSpan(FlowView.java:733)
at javax.swing.text.FlowView.calculateMinorAxisRequirements(FlowView.java:233)
at javax.swing.text.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:717)
at javax.swing.text.BoxView.checkRequests(BoxView.java:935)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
at javax.swing.text.BoxView.calculateMinorAxisRequirements(BoxView.java:903)
at javax.swing.text.BoxView.checkRequests(BoxView.java:935)
at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:343)
at javax.swing.text.BoxView.layout(BoxView.java:708)
at javax.swing.text.BoxView.setSize(BoxView.java:397)
...
</pre><br />
This error is particularly insidious because it takes around ten minutes to show itself and sometimes not at all. If you look at the code for this class the line in question, starts with "startsFrom = break", only accesses two local variables both of which have been previously referenced in the method.<br />
<br />
<pre name="code" class="java"> Segment s = getText(pstart, pend);
s.first();
BreakIterator breaker = getBreaker();
breaker.setText(s);
// Backward search should start from end+1 unless there's NO end+1
int startFrom = end + (pend > end ? 1 : 0);
for (;;) {
startFrom = breaker.preceding(s.offset + (startFrom - pstart))
+ (pstart - s.offset);
if (startFrom > start) {
// The break spot is within the view
bs[ix++] = startFrom;
} else {
break;
}
}
</pre><br />
The most direct way to rule out a JIT error is to disable compilation for just this single method, here is an example; but you can fine more in the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html">documentation for the command line java tool</a>.<br />
<br />
<pre name="code" class="java">javaThing -XX:CompileCommand=exclude,javax/swing/text/GlyphView,getBreakSpot
</pre><br />
When this parameter is added, the problem goes away. - since we have ruled out enemy action by code or a concurrency issue we can be more sure this is a JIT issue. Now as part of the bug logging for this I output diagnostics for this single method, and found out that the problem, didn't occur until the method was JITted for a fifth time.<br />
<br />
<pre name="code" class="java">javaThing -XX:CompileCommand=print,javax/swing/text/GlyphView,getBreakSpot
</pre><br />
Here is some diagnostic output seen with the above command:<br />
<br />
<pre name="code" class="java">Compiled method (c2) 914078 33142 4 javax.swing.text.GlyphView::getBreakSpot (247 bytes)
total in heap [0x00002aaab0749e10,0x00002aaab0750fe0] = 29136
relocation [0x00002aaab0749f38,0x00002aaab074a1e8] = 688
constants [0x00002aaab074a200,0x00002aaab074a2a0] = 160
main code [0x00002aaab074a2a0,0x00002aaab074cde0] = 11072
stub code [0x00002aaab074cde0,0x00002aaab074ce40] = 96
oops [0x00002aaab074ce40,0x00002aaab074ce58] = 24
metadata [0x00002aaab074ce58,0x00002aaab074d058] = 512
scopes data [0x00002aaab074d058,0x00002aaab074ea20] = 6600
scopes pcs [0x00002aaab074ea20,0x00002aaab0750c50] = 8752
dependencies [0x00002aaab0750c50,0x00002aaab0750c80] = 48
handler table [0x00002aaab0750c80,0x00002aaab0750e90] = 528
nul chk table [0x00002aaab0750e90,0x00002aaab0750fe0] = 336
OopMapSet contains 113 OopMaps
#0
OopMap{[8]=Oop [32]=Oop [40]=Oop off=892}
#1
OopMap{[32]=Oop [40]=Oop off=960}
#2
OopMap{[32]=Oop [40]=Oop off=980}
#3
OopMap{[32]=Oop [40]=Oop [48]=Oop off=1048}
#4
OopMap{[32]=Oop [40]=Oop [48]=Oop off=1084}
#5
OopMap{[0]=Oop [24]=Oop [48]=Oop [56]=Oop [80]=Oop off=2500}
#6
OopMap{rbx=Oop rdi=Oop [32]=Oop [40]=Oop [112]=Oop off=2533}
#7
OopMap{rbx=Oop rdi=Oop r14=Oop [32]=Oop [112]=Oop off=3081}
#8
OopMap{rbx=Oop rdi=Oop r14=Oop [32]=Oop [40]=Oop [112]=Oop off=3190}
#9
OopMap{[8]=Oop [32]=Oop [40]=Oop off=4408}
#10
OopMap{[32]=Oop [40]=Oop [48]=Oop off=4640}
#11
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=5232}
#12
OopMap{rbp=Oop [0]=NarrowOop [32]=Oop off=5364}
#13
OopMap{[32]=Oop [40]=Oop [48]=Oop off=5408}
#14
OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5436}
#15
OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5468}
#16
OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5524}
#17
OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop [88]=Oop off=5552}
#18
OopMap{[32]=Oop [40]=Oop [48]=Oop [64]=Oop [72]=Derived_oop_[64] [112]=Oop off=5608}
#19
OopMap{[8]=Oop [32]=Oop off=5680}
#20
OopMap{rbp=Oop off=5720}
#21
OopMap{rbp=Oop off=5752}
#22
OopMap{rbp=Oop [24]=NarrowOop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop [56]=Oop [64]=Oop [88]=Oop off=5812}
#23
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop [88]=Oop off=5960}
#24
OopMap{[0]=Oop [24]=Oop [48]=Oop [56]=Oop [72]=Oop [88]=NarrowOop off=6056}
#25
OopMap{[40]=Oop off=6088}
#26
OopMap{[0]=Oop off=6120}
#27
OopMap{[8]=Oop [24]=Oop [56]=Oop [72]=Oop [112]=Oop off=6216}
#28
OopMap{[0]=Oop [32]=NarrowOop [40]=Oop off=6284}
#29
OopMap{rbp=Oop [16]=Oop [40]=Oop [64]=Oop [112]=Oop off=6384}
#30
OopMap{[0]=Oop off=6412}
#31
OopMap{[0]=Oop [16]=Oop [32]=NarrowOop [40]=Oop [48]=Oop off=6488}
#32
OopMap{rbp=Oop [16]=Oop [40]=Oop [48]=Oop off=6560}
#33
OopMap{[32]=Oop [40]=Oop [48]=Oop [64]=Oop [112]=Oop off=6608}
#34
OopMap{[8]=Oop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop off=6768}
#35
OopMap{rbp=NarrowOop [0]=Oop [16]=Oop [32]=Oop [40]=NarrowOop off=6860}
#36
OopMap{[0]=Oop [16]=Oop [32]=NarrowOop [40]=Oop [48]=Oop off=6988}
#37
OopMap{rbp=Oop [32]=Oop off=7024}
#38
OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=7260}
#39
OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=7344}
#40
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [60]=NarrowOop [64]=Oop off=7452}
#41
OopMap{rbp=NarrowOop [32]=Oop off=7476}
#42
OopMap{rbp=NarrowOop [0]=Oop off=7524}
#43
OopMap{[32]=Oop [40]=Oop [48]=Oop off=7588}
#44
OopMap{[32]=Oop [40]=Oop [48]=Oop off=7616}
#45
OopMap{[32]=Oop [40]=Oop [48]=Oop off=7632}
#46
OopMap{rbp=NarrowOop [32]=Oop off=7676}
#47
OopMap{rbp=NarrowOop [0]=Oop off=7724}
#48
OopMap{[0]=Oop [16]=Oop [28]=NarrowOop [40]=Oop [48]=Oop [56]=NarrowOop [64]=Oop off=7868}
#49
OopMap{[8]=Oop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop [56]=Oop off=7916}
#50
OopMap{rbp=Oop [16]=Oop [24]=NarrowOop off=8016}
#51
OopMap{rbp=Oop [16]=Oop [28]=NarrowOop off=8080}
#52
OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=8152}
#53
OopMap{rbp=Oop [8]=NarrowOop off=8212}
#54
OopMap{rbp=NarrowOop [32]=Oop off=8236}
#55
OopMap{rbp=Oop [16]=NarrowOop off=8272}
#56
OopMap{rbp=NarrowOop [0]=Oop off=8320}
#57
OopMap{rbp=Oop [12]=NarrowOop off=8360}
#58
OopMap{rbp=NarrowOop [32]=Oop off=8400}
#59
OopMap{rbp=Oop [12]=NarrowOop off=8460}
#60
OopMap{rbp=NarrowOop [0]=Oop off=8508}
#61
OopMap{rbp=Oop [24]=NarrowOop [40]=Oop off=8572}
#62
OopMap{rbp=Oop off=8600}
#63
OopMap{rbp=Oop [8]=Oop [28]=NarrowOop off=8640}
#64
OopMap{rbp=Oop [8]=Oop [20]=NarrowOop [112]=Oop off=8704}
#65
OopMap{rbp=Oop [16]=Oop [24]=Oop [48]=Oop off=8788}
#66
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=8912}
#67
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9036}
#68
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9160}
#69
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9284}
#70
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9408}
#71
OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9532}
#72
OopMap{off=9556}
#73
OopMap{off=9580}
#74
OopMap{off=9604}
#75
OopMap{[112]=Oop off=9628}
#76
OopMap{rbp=Oop [8]=Oop [24]=Oop [32]=NarrowOop off=9696}
#77
OopMap{rbp=Oop [8]=Oop [24]=NarrowOop off=9760}
#78
OopMap{off=9784}
#79
OopMap{off=9812}
#80
OopMap{off=9836}
#81
OopMap{off=9860}
#82
OopMap{off=9884}
#83
OopMap{off=9908}
#84
OopMap{off=9932}
#85
OopMap{off=9956}
#86
OopMap{off=9980}
#87
OopMap{off=10004}
#88
OopMap{off=10028}
#89
OopMap{rbp=Oop [16]=Oop [28]=NarrowOop off=10092}
#90
OopMap{rbp=Oop [16]=Oop [24]=Oop [48]=Oop off=10176}
#91
OopMap{off=10200}
#92
OopMap{off=10224}
#93
OopMap{off=10248}
#94
OopMap{off=10272}
#95
OopMap{off=10296}
#96
OopMap{off=10320}
#97
OopMap{off=10344}
#98
OopMap{off=10368}
#99
OopMap{off=10392}
#100
OopMap{off=10416}
#101
OopMap{off=10440}
#102
OopMap{off=10464}
#103
OopMap{off=10488}
#104
OopMap{off=10512}
#105
OopMap{off=10536}
#106
OopMap{off=10560}
#107
OopMap{off=10584}
#108
OopMap{off=10608}
#109
OopMap{off=10632}
#110
OopMap{off=10656}
#111
OopMap{off=10680}
#112
OopMap{off=11028}
java.lang.NullPointerException
at javax.swing.text.GlyphView.getBreakSpot(GlyphView.java:799)
at javax.swing.text.GlyphView.getBreakWeight(GlyphView.java:724)
at javax.swing.text.html.InlineView.getBreakWeight(InlineView.java:150)
at javax.swing.text.FlowView$LogicalView.getPreferredSpan(FlowView.java:733)
at javax.swing.text.FlowView.calculateMinorAxisRequirements(FlowView.java:233)
at javax.swing.text.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:717)
at javax.swing.text.html.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:157)
at javax.swing.text.BoxView.checkRequests(BoxView.java:935)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
at javax.swing.text.html.ParagraphView.getMinimumSpan(ParagraphView.java:270)
at javax.swing.text.BoxView.calculateMinorAxisRequirements(BoxView.java:903)
</pre> <br />
Now I am still working with the JDK team for a fix for this one; but I do feel I have discovered a useful set of tools for providing some evidence that the JIT compiler is causing my bad day. And more importantly I have a workaround so I can run my tests until this is resolved.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com19tag:blogger.com,1999:blog-2648073517459434852.post-6354345626644557142014-11-06T11:01:00.000+00:002015-02-01T10:12:28.989+00:00Missing stack traces for repeated exceptions (reminder)<a href="http://www.javaspecialists.eu/archive/Issue187.html">A long while ago a optimisation was added to the JVM</a> so that if the same exception is thrown again and again and again a single instance of the Exception is created without the stack trace filled in in order to increase performance. This is an excellent idea unless you are trying to diagnose a problem and you have missed the original error.<br />
<br />
If you forgot about this optimisation you send the afternoon looking at the following log output and weeping slightly. (In my defence I have a little one in the house hence the fuzzy brain and lack of blogging action this year)<br />
<br />
<pre name="code" class="java">java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
...
java.lang.Exception: Uncaught exceptions during test
at oracle.jdevstudio-testware-tests.level0.testADFcMATS(/.../work/mw9111/jdeveloper/jdev/extensions/oracle.jdevstudio-testware-tests/abbot/common-adf/CreateNewCustomAppAndProjectWithName.xml:25)
at oracle.jdevstudio-testware-tests.level0.testADFcMATS(/.../work/mw9111/jdeveloper/jdev/extensions/oracle.jdevstudio-testware-tests/abbot/level0/testADFcMATS.xml:94)
at oracle.abbot.JDevScriptFixture.runTest(JDevScriptFixture.java:555)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at junit.textui.TestRunner.doRun(TestRunner.java:109)
at oracle.abbot.AbbotRunner.run(AbbotRunner.java:614)
at oracle.abbot.AbbotAddin$IdeAbbotRunner.run(AbbotAddin.java:634)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ArrayIndexOutOfBoundsException
[Crickets]
</pre><br />
It turns out that you can turn off this optimisation with a simple flag:<br />
<br />
<pre>java -XX:-OmitStackTraceInFastThrow ....
</pre><br />
In my particular case the actual exception causing this trouble was a NPE from the GlyphView code in JDK8. (One that is being caused by a glitch in hotspot it seems) But that in turn was causing the AIOOBE in some logging code clouding the issue even more.<br />
<br />
This in particular is a good flag to add by default when running your automated tests, particularly in combination with the <a href="/2012/06/catch-stackoverflowerror-by-its-tail.html">stack trace length override</a> I have talked about before.<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com0tag:blogger.com,1999:blog-2648073517459434852.post-13694217475286222662014-05-21T11:13:00.000+01:002014-05-21T11:13:10.017+01:00Reading and writing JAX-RS Link objectsJAX-RS contains a rather nice handy representation of the a <a href="https://java.net/jira/browse/JAX_RS_SPEC-446">Link</a> that can be serialised with and adapter into XML and JSON, unfortunately there is a bug in the JAX-RS spec that means that the standard adapter provided is <a href="https://java.net/jira/browse/JAX_RS_SPEC-446">missing the setters required</a> to deserialise the Link later on.<br />
<br />
This isn't a problem if you are using the JAX-B RI as it appears to be more relaxed than the standard; but it will be a problem for other implementations. There is a further bug if you are using MOXy, aka EclipseLink, to produce either JSON or XML that it will fail and just call <code>toString()</code> because it doesn't like the type adapter being an inner class of the class that is being adapted. (Bug TBC)<br />
<br />
<br />
<table> <tr>
<th>Direction</th>
<th>JAXB RI + JAX-RS Adapter</th>
<th>MOXy + JAX-RS Adapter</th>
<th>MOXy + Outer Adapter</th>
<th>MOXy + Outer Adapter + Setters</th>
<th>MOXy + Inner Adapter (Different class)</th>
</tr>
<tr>
<td>Marshalling</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Unmarshalling</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
</tr>
</table><br />
<br />
The workaround is to create a new adapter as a top level class in order to replace the one provided by the standard. Just quickly it would look something like this:<br />
<br />
<pre name="code" class="java">import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;
public class LinkAdapter
extends XmlAdapter<LinkJaxb, Link> {
public LinkAdapter() {
}
public Link unmarshal(LinkJaxb p1) {
Link.Builder builder = Link.fromUri(p1.getUri());
for (Map.Entry<QName, Object> entry : p1.getParams().entrySet()) {
builder.param(entry.getKey().getLocalPart(), entry.getValue().toString());
}
return builder.build();
}
public LinkJaxb marshal(Link p1) {
Map<QName, Object> params = new HashMap<>();
for (Map.Entry<String,String> entry : p1.getParams().entrySet()) {
params.put(new QName("", entry.getKey()), entry.getValue());
}
return new LinkJaxb(p1.getUri(), params);
}
}
</pre><br />
With a simple POJO to go with it.<br />
<br />
<pre name="code" class="java">import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.namespace.QName;
public class LinkJaxb {
private URI uri;
private Map<QName, Object> params;
public LinkJaxb() {
this (null, null);
}
public LinkJaxb(URI uri) {
this(uri, null);
}
public LinkJaxb(URI uri, Map<QName, Object> map) {
this.uri = uri;
this.params = map!=null ? map : new HashMap<QName, Object>();
}
@XmlAttribute(name = "href")
public URI getUri() {
return uri;
}
@XmlAnyAttribute
public Map<QName, Object> getParams() {
return params;
}
public void setUri(URI uri) {
this.uri = uri;
}
public void setParams(Map<QName, Object> params) {
this.params = params;
}
}
</pre><br />
With this you can read and write the Link objects to and from XML, and JSON with MOXy, to your hearts content.<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com5tag:blogger.com,1999:blog-2648073517459434852.post-86471107144788401672014-05-20T13:09:00.000+01:002014-05-21T11:17:05.789+01:00Declarative Linking in Jersey 2.9 and up<strike>A couple of weeks ago</strike> A couple of months ago I was looking how I was going to engineers new REST API for an Oracle Cloud project. Once of the things I had planned to do was to use the declarative link injection created in Jersey 1.x by Marc Hadley. Sadly this hadn't been forwarded ported yet, so a quick chat to the project lead and I took on the <strike>small</strike> medium sized job of bringing the code up to date.<br />
<br />
One of the things that has changed in the new version is that in JAX-RS 2.0 there is a <code>Link</code> object so rather than being able to only inject String and URI you can also inject the correct rel attributes. This has means that the existing annotations coded by Marc have been merged into once simple set of annotations for both Link headers and for injected properties.<br />
<br />
This functionality is <a href="https://jersey.java.net/documentation/latest/declarative-linking.html">available now</a>, along with a <a href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22declarative-linking%22">simple example.</a> The <a href="https://github.com/jersey/jersey/pull/61">original version of the feature</a> that I committed has some serious limitations that are described later, you will need a version of Jersey post 2.8 or you can build a 2.9-SNAPSHOT image that <a href="https://github.com/jersey/jersey/pull/82">contains my changes</a> currently to implement the example in this blog.<br />
<br />
This blog looks at using this new API to provide simple injection for a collections API. One of the common patterns in RESTful services, in particular those based on JSON, is to have an array of structural links at the top level of the structure. For the purposes of this blog I am going to follow the form of the <a href="http://amundsen.com/media-types/collection/">Collection+JSON</a> hypermedia type.<br />
<br />
<pre name="code" class="javascript">{ "collection" :
{
"version" : "1.0",
"href" : "http://example.org/friends/?offset=10&limit=10",
"links" : [
{"rel" : "create", "href" : "http://example.org/friends/"}
{"rel" : "next", "href" : "http://example.org/friends/?offset=20&limit=10"}
{"rel" : "previous", "href" : "http://example.org/friends/?offset=0&limit=10"}
],
"items" : [
...
]
}
}
</pre><br />
So I can inject the links in the following form, not there is a bunch of boiler plate missing here for clarity. This is not the tidiest code; but in a later cycle it should be possible to simply them somewhat. The design currently uses EL to access properties - this has the advantage of making it possible to write back values as you can represent properties. I can understand it is disliked by some; but I am not sure if I see any value in moving to JavaScript at the moment. Also don't be put of by the @Xml annotations, I am using MOXy for JSON generation - this isn't an XML only thing.<br />
<br />
<pre name="code" class="java">{
@XmlTransient
private int limit, offset; // Getters for these
@XmlTransient
private int modelLimit; // Getters for these
@InjectLink(
resource = ItemsResource.class,
method = "query",
style = Style.ABSOLUTE,
bindings = {@Binding(name = "offset", value="${instance.offset}"),
@Binding(name = "limit", value="${instance.limit}")
},
rel = "self"
)
@XmlElement(name="link")
private String href;
@InjectLinks({
@InjectLink(
resource = ItemsResource.class,
style = Style.ABSOLUTE,
method = "query",
condition = "${instance.offset + instance.limit < instance.modelLimit}",
bindings = {
@Binding(name = "offset", value = "${instance.offset + instance.limit}"),
@Binding(name = "limit", value = "${instance.limit}")
},
rel = "next"
),
@InjectLink(
resource = ItemsResource.class,
style = Style.ABSOLUTE,
method = "query",
condition = "${instance.offset - instance.limit >= 0}",
bindings = {
@Binding(name = "offset", value = "${instance.offset - instance.limit}"),
@Binding(name = "limit", value = "${instance.limit}")
},
rel = "prev"
)})
@XmlElement(name="link")
@XmlElementWrapper(name = "links")
@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
List<Link> links;
....
}
</pre><br />
The original porting of the declarative linking code that exists in version Jersey before 2.8 had very naive code with regards working out what the URI should be for a particular resource, it couldn't deal with any resources that were not at the root of the application, nor would it cope with query parameters which are so important when dealing with collections.<br />
<br />
In theory there could be more than one URI for a particular resource class; but this code does need to assume a 1:1 mapping, the current implementation contains a simple algorithm that walks the Jersey meta-model to try to work out the structure, is this doesn't work in your can you can simple provide another implementation of <a href="https://github.com/jersey/jersey/blob/master/incubator/declarative-linking/src/main/java/org/glassfish/jersey/linking/mapping/ResourceMappingContext.java">ResourceMappingContext</a>.<br />
<br />
Some may question why should I use these ugly annotations when it might be easier just to inject the URI myself? Well the reason is to provide metadata that other tools can use. One of my next jobs is to extend <a href="http://kingsfleet.blogspot.co.uk/2014/04/quick-and-bit-dirty-json-schema.html">this work</a> to generate the hypermedia extensions and for this I need the above metadata. (Waiting on a <a href="https://github.com/eclipse/eclipselink.runtime/pull/7">pull request</a> being approved before I can really get into it).<br />
<br />
Finally it is worth noting that the paging model has its own problems which become apparent if you think of a REST collection as some kind of array that you can safely page over. Concurrent updates along with the lack of state mean that the client can never be sure they have the complete model and should expect to see some items more than once as the model is updated. Cursor or linking based schemes should be considered instead which is yet another good reminder as to why you should always treat the URI as opaque - the sever might need to changes its structure in the future. But that is a entirely different blog for another day.....<br />
<br />
<b>Update: </b> See the following blog for some workarounds <a href="/2014/05/reading-and-writing-jax-rs-link-objects.html">when reading and writing</a> Link objects.<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com3tag:blogger.com,1999:blog-2648073517459434852.post-20428054455026940372014-04-15T10:43:00.000+01:002014-04-15T15:42:15.273+01:00Quick, and a bit dirty, JSON Schema generation with MOXy 2.5.1So I am working on a new REST API for an upcoming Oracle cloud service these days so one of the things I needed was the ability to automatically generate a JSON Schema for the bean in my model. I am using MOXy to generate the JSON from POJO and as of version 2.5.1 of <a href="http://www.eclipse.org/eclipselink/">EclipseLink</a> it now has the ability to generate a JSON Schema from the bean model.<br />
<br />
There will be a more formal solution integrated into Jersey 2.x at a future date; but this solution will do at the moment if you want to play around with this.<br />
<br />
So the first class we need to put in place is a model processor, very much and internal Jersey class, that allows us to amend the resource model with extra methods and resources. To each resource in the model we can add the <code>JsonSchemaHandler</code> which does the hard work of generating a new schema. Since this is a simple POC there is no caching going on here, please be aware of this if you are going to use this in production code.<br />
<br />
<pre name="code" class="java">import com.google.common.collect.Lists;
import example.Bean;
import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBException;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.glassfish.jersey.process.Inflector;
import org.glassfish.jersey.server.ExtendedUriInfo;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.ResourceMethod;
import org.glassfish.jersey.server.model.ResourceModel;
import org.glassfish.jersey.server.model.RuntimeResource;
import org.glassfish.jersey.server.model.internal.ModelProcessorUtil;
import org.glassfish.jersey.server.wadl.internal.WadlResource;
public class JsonSchemaModelProcessor implements ModelProcessor {
private static final MediaType JSON_SCHEMA_TYPE =
MediaType.valueOf("application/schema+json");
private final List<ModelProcessorUtil.Method> methodList;
public JsonSchemaModelProcessor() {
methodList = Lists.newArrayList();
methodList.add(new ModelProcessorUtil.Method("$schema", HttpMethod.GET,
MediaType.WILDCARD_TYPE, JSON_SCHEMA_TYPE,
JsonSchemaHandler.class));
}
@Override
public ResourceModel processResourceModel(ResourceModel resourceModel,
Configuration configuration) {
return ModelProcessorUtil.enhanceResourceModel(resourceModel, true, methodList,
true).build();
}
@Override
public ResourceModel processSubResource(ResourceModel resourceModel,
Configuration configuration) {
return ModelProcessorUtil.enhanceResourceModel(resourceModel, true, methodList,
true).build();
}
public static class JsonSchemaHandler
implements Inflector<ContainerRequestContext, Response> {
private final String lastModified = new SimpleDateFormat(WadlResource.HTTPDATEFORMAT).format(new Date());
@Inject
private ExtendedUriInfo extendedUriInfo;
@Override
public Response apply(ContainerRequestContext containerRequestContext) {
// Find the resource that we are decorating, then work out the
// return type on the first GET
List<RuntimeResource> ms = extendedUriInfo.getMatchedRuntimeResources();
List<ResourceMethod> rms = ms.get(1).getResourceMethods();
Class responseType = null;
found:
for (ResourceMethod rm : rms) {
if ("GET".equals(rm.getHttpMethod())) {
responseType = (Class) rm.getInvocable().getResponseType();
break found;
}
}
if (responseType == null) {
throw new WebApplicationException("Cannot resolve type for schema generation");
}
//
try {
JAXBContext context = (JAXBContext) JAXBContext.newInstance(responseType);
StringWriter sw = new StringWriter();
final StreamResult sr = new StreamResult(sw);
context.generateJsonSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName)
throws IOException {
return sr;
}
}, responseType);
return Response.ok().type(JSON_SCHEMA_TYPE)
.header("Last-modified", lastModified)
.entity(sw.toString()).build();
} catch (JAXBException jaxb) {
throw new WebApplicationException(jaxb);
}
}
}
}
</pre><br />
Note the very simple heuristic in the <code>JsonSchemaHandler</code> code it assumes that for each resource there is a 1:1 mapping to a single JSON Schema element. This of course might not be true for your particular application.<br />
<br />
Now that we have the schema generated in a know location we need to tell the client about it, the first thing we will do is to make sure that there is a suitable link header when the user invokes OPTIONS on a particular resource:<br />
<br />
<pre name="code" class="java">import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.UriInfo;
public class JsonSchemaResponseFilter implements ContainerResponseFilter {
@Context
private UriInfo uriInfo;
@Override
public void filter(ContainerRequestContext containerRequestContext,
ContainerResponseContext containerResponseContext) throws IOException {
String method = containerRequestContext.getMethod();
if ("OPTIONS".equals(method)) {
Link schemaUriLink =
Link.fromUriBuilder(uriInfo.getRequestUriBuilder()
.path("$schema")).rel("describedBy").build();
containerResponseContext.getHeaders().add("Link", schemaUriLink);
}
}
}
</pre><br />
Since this is JAX-RS 2.x we are working with we of course are going bundle all the bit together into a feature:<br />
<br />
<pre name="code" class="java">import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
public class JsonSchemaFeature implements Feature {
@Override
public boolean configure(FeatureContext featureContext) {
if (!featureContext.getConfiguration().isRegistered(JsonSchemaModelProcessor.class)) {
featureContext.register(JsonSchemaModelProcessor.class);
featureContext.register(JsonSchemaResponseFilter.class);
return true;
}
return false;
}
}
</pre><br />
I am not going to show my entire set of POJO classes; but just quickly this is the Resource class with the @GET method required by the schema generation code:<br />
<br />
<pre name="code" class="java">import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/bean")
public class BeanResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Bean getBean() {
return new Bean();
}
}
</pre><br />
And finally here is what you see if you perform a GET on a resource:<br />
<br />
<pre name="code" class="java">GET .../resources/bean
Content-Type: application/json
{
"message" : "hello",
"other" : {
"message" : "OtherBean"
},
"strings" : [
"one",
"two",
"three",
"four"
]
}
</pre><br />
And OPTIONS:<br />
<br />
<pre name="code" class="java">OPTIONS .../resources/bean
Content-Type: text/plain
Link: <http://.../resources/bean/$schema>; rel="describedBy"
GET, OPTIONS, HEAD
</pre><br />
And finally if you resolve the schema resource:<br />
<br />
<pre name="code" class="java">GET .../resources/bean/$schema
Content-Type: application/schema+json
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "example.Bean",
"type" : "object",
"properties" : {
"message" : {
"type" : "string"
},
"other" : {
"$ref" : "#/definitions/OtherBean"
},
"strings" : {
"type" : "array",
"items" : {
"type" : "string"
}
}
},
"additionalProperties" : false,
"definitions" : {
"OtherBean" : {
"type" : "object",
"properties" : {
"message" : {
"type" : "string"
}
},
"additionalProperties" : false
}
}
}
</pre><br />
There is a quite a bit of work to do here, in particular generating the hypermedia extensions based on the <a href="https://jersey.java.net/documentation/latest/user-guide.html#declarative-linking">declarative linking</a> annotations that I forward ported into Jersey 2.x a little while back. But it does point towards a solution and we get to exercise a variety of solutions to get something working now.<br />
<br />
<div class="blogger-post-footer"><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2176345-1";
urchinTracker();
</script></div>Gerard Davisonhttp://www.blogger.com/profile/16521924431312439170noreply@blogger.com4