juneau-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Digest <sl...@digest.ai>
Subject Digest for ASF's Slack
Date Wed, 31 May 2017 12:01:46 GMT
Here’s your digest for today! 
#dev-juneau
undefined: Now that I’m thinking about it, I did see evidence of duplicate parameters being
generated in my console output.  Perhaps my testcases don’t catch the issue because I’m
simply ensure the correct value is received on the server side and duplicate parameters are
simply being overwritten.
undefined: I'm not sure what if anything the http spec has to say about it, but i would be
in favor of a runtime exception rather than submitting a get request with the same parameter
specified twice
undefined: The HTTP spec allows it.  For example, one common way of representing lists is
duplication of keys…e.g. &amp;key=val1&amp;key=val2&amp;key=val3.  But some
sort of RuntimeException in this case is a good idea.
undefined: Brings up an interesting point, when binding a rest proxy where you expect the
upstream to fail on certain conditions, whether there's a means to configure the client to
check that conditionals are / are not met
 I suppose that logic could go in a request I tercweptor
 Request interceptor interface is not great for that use case though. Can be tricky to get
at the params, then only have httpcomponents objects to work with, and method signature is
void so any abort would have to be an HttpException
undefined: I’m able to reproduce the first issue…
```
	@Remoteable(path="/testRequestBeanProxy")
	public static interface RequestBeanProxy {

		@RemoteMethod(httpMethod="GET", path="/test1")
		String queryIfNE1(@RequestBean RequestBean1 rb);

		public static interface RequestBean1 {
			@QueryIfNE(value="a", serializer=DummyPartSerializer.class)
			List&lt;String&gt; getA();
		}

		public static class RequestBean1Impl implements RequestBean1 {
			@Override
			@BeanProperty(name="b")
			public List&lt;String&gt; getA() {
				return new AList&lt;String&gt;().append("foo").append("bar");
			}
		}
	}
```
The problem is that it’s being interpreted as two different bean properties:  “a” and
“b”.  So we’re serializing the parameters twice.
undefined: I’m not able reproduce _when @RequestBean is a class with @BeanProperty and @QueryNE
on each getter, no interface involved aside from Serializable - remote proxy works, sort of,
but with each execution i’m getting some number of java.lang.RuntimeException: org.apache.juneau.BeanRuntimeException:
org.apache.streams.twitter.api.UsersLookupRequest: Class is not a bean.  Reason=‘null’_

Here’s my code…
```
		@RemoteMethod(httpMethod="GET", path="/test3")
		String queryIfNE3(@RequestBean RequestBean2 rb);

		public static class RequestBean2 {
			@BeanProperty
			@QueryIfNE(value="a", serializer=DummyPartSerializer.class)
			public List&lt;String&gt; getX() {
				return new AList&lt;String&gt;().append("foo").append("bar");
			}
			@BeanProperty
			@QueryIfNE(value="b", serializer=DummyPartSerializer.class)
			public List&lt;String&gt; getY() {
				return new AList&lt;String&gt;().append("foo").append("bar");
			}
		}
```
 Can I see what UsersLookupRequest looks like?
undefined: Yep just a sec I'll sync my branch
undefined: I don’t understand this one: _when @RequestBean is an interface with @QueryNE(value=),
which extends a class with @BeanProperty - request parameter appears once in the request but
result of remote proxy call threw exception_

Can you show me a pseudocode example of how the request bean is defined?
undefined: jamesbognar: <https://github.com/steveblackmon/incubator-streams/blob/STREAMS-504/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/UsersLookupRequest.java>
 jamesbognar: I had tried putting an interface with proxy-related annotations around the core
class - the core class being <https://github.com/steveblackmon/incubator-streams/blob/STREAMS-504/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/UsersLookupRequest.java>
minus the @QueryIfNE annotations.
 there is sound logic to keeping the proxy-behavior annotations seperate from the bean serialization
annotations (i think) although i'll grant that i am very attached to source generating all
of my beans from jsonschema.  which works great for beans with basic annotations but breaks
down when you also need the bean to hold classes related to api protocol
undefined: I’ll try to reproduce the problem using your class.  Thanks!
 On a side note, I wonder if we should rename @BeanProperty(name) to @BeanProperty(value)
to match Jackson.  It looks cleaner that way.
 Or include both name and value and make them synonymous.
undefined: when @BeanProperty and @QueryIfNE are right next to each other like that it does
stand out as incongruous
undefined: yea
 Perhaps both should have both ‘name’ and ‘value’, and you can just choose the one
you want.
 So @BeanProperty(“foo”) and @BeanProperty(name=“foo”) would mean the same thing.
undefined: cool, at least on that annotation i dont see a need for more than one field
undefined: I was able to reproduce the “Class is not a bean” exception.  It was a race
condition.  I have a fix for it.
 The fix for the duplicate parameters will take more work.  I need to change the way I find
bean property method annotations.  It’s a hassle because annotations on methods are not
inherited, so I have to search the class hierarchy for the “same” method on parent classes.
 Also note that if you plan on using the proxy class in a multithreaded environment, you’ll
need to call the pooled() method on the RestClientBuilder class.  Otherwise, you’ll see
“Connection still allocated” exceptions thrown from within HttpClient.
 One side note…..with Juneau, you can define fluent-style setters, so there’s no need
for the separate setX() and withX() methods in the UsersLookupRequest class.
undefined: All good to know. Thanks james!
undefined: Do you think it would be better to wrap the http request in the proxy inside a
synchronized block so that you don't need a pooled http client?
 I could add that option as a parameter on the getRemoteableProxy method.
undefined: Id hope we can make it fully parallel, up to a max # of concurrent threads in the
pool. Makes more sense for streams use case to have a singleton accessor class and many concurrent
connections
 A lot of time at scale is spent with http set up year down and waiting for external service
undefined: Ok.  I'll just add to the javadoc that you should use pooled() if you plan on using
the proxy multithreaded.
undefined: :+1: 
undefined: Another quick note….if you’re using the @BeanProperty annotation on methods,
there are no naming restrictions.  Anything with one parameter is considered a setter, and
anything with zero parameters is considered a getter.  It allows you to define fluent-style
setters such as the following example from AtomFeedResource…

```
			feed =
				feed("tag:<http://juneau.sample.com|juneau.sample.com>,2013:1", "Juneau ATOM specification",
"2013-05-08T12:29:29Z")
				.subtitle(text("html").text("A &lt;em&gt;lot&lt;/em&gt; of effort went
into making this effortless"))
				.links(
					link("alternate", "text/html", "<http://www.sample.com/>").hreflang("en"),
					link("self", "application/atom+xml", "<http://www.sample.com/feed.atom>")
				)
				.rights("Copyright (c) 2016, Apache Foundation")
				.generator(
					generator("Juneau").uri("<http://juneau.apache.org/>").version("1.0")
				)
				.entries(
					entry("tag:<http://juneau.sample.com|juneau.sample.com>,2013:1.2345", "Juneau ATOM
specification snapshot", "2013-05-08T12:29:29Z")
					.links(
						link("alternate", "text/html", "<http://www.sample.com/2012/05/08/juneau.atom>"),
						link("enclosure", "audio/mpeg", "<http://www.sample.com/audio/juneau_podcast.mp3>").length(1337)
					)
					.published("2013-05-08T12:29:29Z")
					.authors(
						person("James Bognar").uri(new URI("<http://www.sample.com/>")).email("<mailto:jamesbognar@apache.org|jamesbognar@apache.org>")
					)
					.contributors(
						person("Barry M. Caceres")
					)
					.content(
						content("xhtml")
						.lang("en")
						.base("<http://www.apache.org/>")
						.text("&lt;div&gt;&lt;p&gt;[Update: Juneau supports ATOM.]&lt;/p&gt;&lt;/div&gt;")
					)
				);
```


#general


#random



Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message