Web Preview Image

Hi all.

Does anyone have a clue on how can I show a preview of a url like an image in Servoy? I don’t want the user to interact with the web page, just want to show a preview to him. The idea is like in a new status in facebook that show a little image with a description of the web page inside of the status.

Thanks in advanced,

Andres

Have a look at the new Velocity Services…

Get the latest Velocity version https://www.servoyforge.net/projects/ve … port/files
Learn about Velocity Services: https://www.servoyforge.net/projects/ve … vices/wiki

In particular, I’ve found a web service that does exactly what you need.
Here is the config.json configuration for it: https://www.servoyforge.net/boards/29/topics/677

Then you will be able to invoke it in Servoy using:

var bytes = plugins.Velocity.invokeServivce('pageKeeper', {url: 'http://www.servoy.com/', size: 'x'});

Where size can be: t (90x68), s (120x90), m (200x150), l (400x300), x (480x360)

Easy enough thanks to Velocity new services capabilities!

thanks patrick!

Just what I needed, I’ll have a look at Velocity

You really should. For all sorts of reasons! ;)

Patrick, I’ve tried Velocity and can’t make it work.

Downaloded v2.2.3, copied all the files

  • rewrote “commons.jnlp” with the one inside the folder ForClientServices
  • rewrote the config.json inside this folder with the following:
VelocityReport
{
	services: {
		pageKeeper: {
			url: "http://pagepeeker.com/thumbs.php?wait=1&size=$size&url=$url",
			method: "get",
			processType: "client",
			params: {
				size: "String",
				url: "String",
			},
			returns: {
				image: "byte[]" 
			}
		}
	}
}
  • Configured my path and URL in the servoy admin page

Then, in the VelocityReport solution added a button to test the following function:

	var bytes = plugins.Velocity.invokeService('pageKeeper', {url: 'http://www.servoy.com/', size: 's'})
	fImagen = bytes

Where fImagen is a form variable to show in the form the image of the URL.
But when launch this method I get the following error:

2012-12-13 11:24:01,531 ERROR [http-8080-1] com.servoy.j2db.util.Debug - Throwable [A466E59F-53C4-4AD6-90DB-294A3B3A7B5C VelocityReport]
java.lang.NullPointerException
	at net.stuff.servoy.plugin.velocity.VelocityProvider.invokeService(VelocityProvider.java:170)
	at net.stuff.servoy.plugin.velocity.VelocityProvider.js_invokeService(VelocityProvider.java:157)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:158)
	at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:311)
	at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:1774)
	at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:837)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:158)
	at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:406)
	at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3192)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:156)
	at com.servoy.j2db.scripting.ScriptEngine.executeFunction(ScriptEngine.java:574)
	at com.servoy.j2db.debug.RemoteDebugScriptEngine.executeFunction(RemoteDebugScriptEngine.java:398)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:4930)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:4811)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:4677)
	at com.servoy.j2db.FormController$ScriptExecuter.executeFunction(FormController.java:4524)
	at com.servoy.j2db.ui.BaseEventExecutor.fireEventCommand(BaseEventExecutor.java:271)
	at com.servoy.j2db.ui.BaseEventExecutor.fireActionCommand(BaseEventExecutor.java:217)
	at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor.handleEvent(WebEventExecutor.java:458)
	at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor.onEvent(WebEventExecutor.java:399)
	at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor$2.onEvent(WebEventExecutor.java:180)
	at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:177)
	at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:312)
	at org.apache.wicket.request.target.component.listener.BehaviorRequestTarget.processEvents(BehaviorRequestTarget.java:157)
	at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
	at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1279)
	at org.apache.wicket.RequestCycle.step(RequestCycle.java:1358)
	at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1465)
	at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
	at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:486)
	at com.servoy.j2db.server.servlets.Zt.doGet(Zt.java:14)
	at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:138)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:554)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Unknown Source)

It seems he can’t get the service I’m invoking. Did I skip some step in the configuration?

Thanks,
Andres

pd: Should I put this in the Velocity plugin forum?

1/ use the latest (v3.0RC is perfectly fine to use and adds fixes and enhancements to services in particular)
2/ your config.json should be well formed, otherwise it cannot be loaded. I see for example that there is a missing “:” after VelocityReport.

  • You could use this online validator: http://www.freeformatter.com/json-validator.html to validate your json (check the “Accept non-quoted names” before validating)
    3/ is the solution you are using named ‘VelocityReport’? Otherwise the first object should be the name of the solution your script invoking the service is located.

that was it, patrick, the JSON was bad formed. Now it works fine and does exactly what I wanted and very easy to use.

Thank you very much!

Excellent. Glad you like it!

Patrick -

I think of Velocity’s sweet spot as setting up web services, not grabbing them. It seems to me that one call with the included http plugin is the way to go here:

mediaColumn = plugins.http.getMediaData("http://pagepeeker.com/thumbs.php?size=x&url=http://data-mosaic.com")

Or am I missing something?

I think you ARE missing quite a few things, yes:

1/you define services in config.json, which is a central place for external web services configuration (and note that config.json now accepts #include and #parse if you want to organize your solutions/services configuration in various - easy to manage - related files), also note that the config.json configuration is dynamic, meaning you can modify it while your server is running, nothing to redeploy, the changes will be picked up automatically upon the next call/request.

2/ the invocation of services can be synchronous or asynchronous, depending on whether you are doing

var result = plugins.Velocity.invokeService(serviceName, params);

or

plugins.Velocity.invokeService(serviceName, params, callbackFunction);

3/ when you invoke services programmatically, the services you invoke can be called from the client side or the server side, simply define a processType: “client” or processType: “server” - the plugin takes care of all the plumbing and uses a dedicated thread if it is called asynchronously (no need to span a headless client for example).

4/ not only can you call the services programmatically, but you can also ask Velocity to invoke them during a request or a response cycle, using processType: “pre” or processType: “post”.

  • With ‘pre’ the service will be invoked upon a request on a path/route that you define (route property in the service object), and the result of the invocation will be added to the request object (a plain JavaScript object) that you get in your vr_getContext() method, the result will be inserted in the request.parameters collection, with a property name that you can define (insertAs in config.json) or bearing the name of the service.
  • With ‘post’, the service will be invoked during the construction of the response, still on a path/route you’ve defined, so the service will be called after you have returned a response in your vr_getContext() method, and its results will be added to the context of the response (with a property name defined by insertAs in config.json or the service name if no insertAs is given), then the added information can be used to fill a template (of any sort), or to return a JSON or XML response automatically.

5/ you will likely have to concatenate a string when you are calling your service:

var theURL = "http://data-mosaic.com";
var theSize = 'x';
mediaColumn = plugins.http.getMediaData("http://pagepeeker.com/thumbs.php?size="+theSize+"&url="+theURL);

personally, I find the code below more readable/maintanable:

var theURL = "http://data-mosaic.com";
var theSize = 'x';
mediaColumn = plugins.Velocity.invokeService('pageKeeper', {url: theURL, size: theSize};

Knowing as well that if you ever need to change the URL of the service or add some extra parameters, you can do so in the config.json without the need to redeploy.

I would think that’s plenty of reasons why using Velocity to invoke external services makes more sense!

I think the pre and post aspect is the only advantage (and even these are not something one can’t handle in code). Everything else can easily be accomplished with a simple UI for future proofing, creating API method(s) to run code taking various parameters, headless client plugin if you need asynchronous (can be a parameter flag), json/xml/various response types can already be specified, etc.

I see Velocity as vastly superior to rolling your own jsp’s or using Servoy’s web services plugin for creating end points but to grab simple web services like this I’m still not seeing the big deal.

The tight integration with Velocity is a plus IMHO.
And sure, you can always reinvent the wheel, but I would think for people who do not want to have to build their own " ‘simple’ UI for future proofing, creating API method(s) to run code taking various parameters, headless client plugin if you need asynchronous (can be a parameter flag), json/xml/various response types… ", having it readily available and working with a few lines of configuration can be a big deal.
Feel free not to use of course! ;)

And BTW, spawning a headless client to invoke a service asynchronously will cost you a license and a good deal of overhead.
While doing it in Velocity will only create a Thread for the duration of the call (on the client or the server, depending on the processType).
Put that in the advantages as well…

ptalbot:
The tight integration with Velocity is a plus IMHO.
And sure, you can always reinvent the wheel, but I would think for people who do not want to have to build their own " ‘simple’ UI for future proofing, creating API method(s) to run code taking various parameters, headless client plugin if you need asynchronous (can be a parameter flag), json/xml/various response types… ", having it readily available and working with a few lines of configuration can be a big deal.
Feel free not to use of course! ;)

But installing and setting up a few lines of configuration is not always such a small deal either. Always a learning curve, a new place to keep track of things, a separate piece to keep upgraded, SVN’s to setup, etc – that has to be accounted for. Just because something is free or already done doesn’t mean it’s free to the user.

Reminds me of Joel’s famous article on the economics of substitutes and compliments. A quote:

Debugged code is NOT free, whether proprietary or open source. Even if you don’t pay cash dollars for it, it has opportunity cost, and it has time cost. … To summarize, I’m not very impressed by people who try to prove wild economic things about free-as-in-beer software, because they’re just getting divide-by-zero errors as far as I’m concerned.

So the easiest solution to the OP’s question is:

mediaColumn = plugins.http.getMediaData("http://pagepeeker.com/thumbs.php?size=x&url=http://data-mosaic.com")

…followed by some abstractions that the user codes as more power/flexibility is needed incrementally and then followed by going the full Velocity route.

If you’re using web services all day long every day – then I think that the Velocity route makes a lot of sense. If not, it is just another thing that you have to keep track of and when you come back to it three months later (like when you’re installing a new server or needing to grab another simple web service) you have to figure it all out again.

This is an important distinction I think.

Velocity is indeed more efficient (memory- and license wise) for asynchronous calls.
Only since Servoy 6.1 you can use callbacks with the HTTP plugin and they are client only (not client or server like Velocity is). Before 6.1 you would need to use the HC to get some async calling.
Velocity supports Servoy 5.2 and up for this.

Another benefit of using Velocity web services is that any request you make the response can be XML or JSON. Velocity simply will give you a JS object and you can start using it right away. When using the HTTP plugin you need to re-serialise this first (easy for JSON, not so for XML).

And in general it’s just easier to do dynamic HTTP stuff with the Velocity plugin than with the HTTP plugin.

ptalbot:
And BTW, spawning a headless client to invoke a service asynchronously will cost you a license and a good deal of overhead.
While doing it in Velocity will only create a Thread for the duration of the call (on the client or the server, depending on the processType).
Put that in the advantages as well…

I’m just waiting for you to come out with a Velocity to run SWC on one license :)

Hi David,

david:
I’m just waiting for you to come out with a Velocity to run SWC on one license :)

I hope you know where to find the ‘Donate’ button on the Velocity project.

david:
But installing and setting up a few lines of configuration is not always such a small deal either. Always a learning curve, a new place to keep track of things, a separate piece to keep upgraded, SVN’s to setup, etc – that has to be accounted for. Just because something is free or already done doesn’t mean it’s free to the user.

Nothing is totally free of course, but if you never start using technologies that can give your solution a huge boost in productivity, then you’ll get stuck with yesterday’s technology. Is that what you are recommending?
Based on that principle of shying from a certain learning curve, even when there are proven benefits, you would still be using a text editor and writing static html for your web 1.0 sites then, is that it?

I’d say to users “try Velocity” as soon as you can - it’s not that difficult anyway, and it will open your dev practices to such a range of extended options that the ‘learning curve’ will be well invested in no time!
I’ve been involved in all sorts of projects where the use of Velocity has given users the opportunity to get to the next level, so when I see people who don’t know about it, I direct them to it, because once they’ve mastered the basics they will be empowered with a range of powerful techniques that will generally make their solution better.

As to your quote, I’ve never said Open Source was to be free, and costs nothing, so I don’t get your point…

david:
If you’re using web services all day long every day – then I think that the Velocity route makes a lot of sense. If not, it is just another thing that you have to keep track of and when you come back to it three months later (like when you’re installing a new server or needing to grab another simple web service) you have to figure it all out again.

This is an important distinction I think.

So based on that distinction, I suppose you are saying to users interested in your frameworks that they should not bother, but do it themselves because they can obviously do all of that in Servoy, right?
Why going through the learning curve of your frameworks, right? ;)

ptalbot:
So based on that distinction, I suppose you are saying to users interested in your frameworks that they should not bother, but do it themselves because they can obviously do all of that in Servoy, right?
Why going through the learning curve of your frameworks, right? ;)

Exactly. It’s about the 3’rd option we recommend:

1- If you need a simple solution with a form or two, fire up Servoy and get it done right away.

2- Keep iterating with improvements over time.

3- If you find yourself writing a full application frameworks, time to check our stuff out.

You forgot one line of code:
foundset.sort(“priority desc”) :twisted: ;)