Best way to display picture attachments in playframework? - java

I'm using playframework-1.2.3 and i have a data model looks like this:
public class Item extends Model {
...
public Blob img;
}
The images are stored with no extensions(like "0f4fb5da-ed95-4c22-b3ec-725489285848") in my system.
I display the images this way followed the tutor:
<img src="#{items.getImg(i.id)}" height="210px"/>
But what i want is not request the controller every time i display it, is there any way allow me to display images with static file link ?
This may need two steps:
1.stored images with a extension.
2.change the file attachments dir under /public.
So , can any one help ?

Is there any real problem having it go via your controller? This actually gives you a better level of abstraction.
However, if you did want to do it statically, then you could create a new staticDir route, rather than moving your images into your public folder. For example
GET /img/ staticDir:usrImages
If you need any level of security over who can see these images though, I would caution against using a public access method like this. Using a controller allows you to do a session check, to ensure the user has appropriate access to view the image.
Edit - I would suggest reading Peter Hilton's blog on this - http://www.lunatech-research.com/playframework-file-upload-blob

Related

Programatically embed a video in a slideshow using Apache Open Office API

I want to create a plugin that adds a video on the current slide in an open instance of Open Office Impress by specifying the location of the video automatically. I have successfully added shapes to the slide. But I cannot find a way to embed a video.
Using the .uno:InsertAVMedia I can take user input to choose a file and it works. How do I want to specify the location of the file programmatically?
CONCLUSION:
This is not supported by the API. Images and audio can be inserted without user intervention but videos cannot be done this way. Hope this feature is released in subsequent versions.
You requested information about an extension, even though the code you are using is quite different, using a file stream reader and POI.
If you really do want to develop an extension, then start with one of the Java samples. An example that uses Impress is https://wiki.openoffice.org/wiki/File:SDraw.zip.
Inserting videos into an Impress presentation can be difficult. First be sure you can get it to work manually. The most obvious way to do that seems to be Insert -> Media -> Audio or Video. However many people use links to files instead of actually embedding the file. See also https://ask.libreoffice.org/en/question/1898/how-to-embed-video-into-impress-presentation/.
If embedding is working for your needs and you want to automate the embedding by using an extension (which seems to be what your question is asking), then there is a dispatcher method called InsertAVMedia that does this.
I do not know offhand what the parameters are for the call. See https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=61127 for how to look up parameters for dispatcher calls.
EDIT
Here is some Basic code that inserts a video.
sub insert_video
dim document as object
dim dispatcher as object
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(document, ".uno:InsertAVMedia", "", 0, Array())
end sub
From looking at InsertAVMedia in sfx.sdi, it seems that this call does not take any parameters.
EDIT 2
Sorry but InsertVideo and InsertImage do not take parameters either. From svx.sdi it looks like the following calls take parameters of some sort: InsertGalleryPic, InsertGraphic, InsertObject, InsertPlugin, AVMediaToolBox.
However according to https://wiki.openoffice.org/wiki/Documentation/OOoAuthors_User_Manual/Getting_Started/Sometimes_the_macro_recorder_fails, it is not possible to specify a file for InsertObject. That documentation also mentions that you never know what will work until you try it.
InsertGraphic takes a FileName parameter, so I would think that should work.
It is possible to add an XPlayer on the current slide. It looks like this will allow you to play a video, and you can specify the file's URL automatically.
Here is an example using createPlayer: https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=57699.
EDIT:
This Basic code works on my system. To play the video, simply call the routine.
sub play_video
If Video_flag = 0 Then
video =converttoURL( _
"C:\Users\JimStandard\Downloads\H264_test1_Talkinghead_avi_480x360.avi")
Video_flag = 1
'for windows:
oManager = CreateUnoService("com.sun.star.media.Manager_DirectX")
' for Linux
' oManager = CreateUnoService("com.sun.star.media.Manager_GStreamer")
oPlayer = oManager.createPlayer( video )
' oPlayer.CreatePlayerwindow(array()) ' crashes?
'oPlayer.setRate(1.1)
oPlayer.setPlaybackLoop(False)
oPlayer.setMediaTime(0.0)
oPlayer.setVolumeDB(GetSoundVolume())
oPlayer.start() ' Lecture
Player_flag = 1
Else
oPlayer.start() ' Lecture
Player_flag = 1
End If
End Sub

How do I invoke a template from another template in Play Framework?

I have a template accountlist.scala.html looking like this:
#(accounts: models.domain.AccountList)
#titlebar = {<p>some html</p>}
#content = {
#for(account <- accounts) {
<p>#account.name</p>
}
}
#main(titlebar)(content)
... and another template account.scala.html like this:
#(account: models.domain.Account)
#titlebar = {<p>#account.name</p>}
#content = {
#for(transaction <- account.getTransactions()) {
<p>#transaction.detail</p>
}
}
#main(titlebar)(content)
From both of them I am invoking the template main.scala.html.
I have access to the entire Account POJO in the first view accountlist.scala.html, so really there is no need for me to invoke the server to get the details of the account when I go to the view in which I display the details. I would just like to change view on the client side. How could I call the second view account.scala.html from the view accountlist.scala.html a user clicks on an account in the list? I am ready to change the templates as needed.
I have provided a previous answer, which is still available at the end of this post. From your comments, however I understand that you are asking for something else without understanding how dangerous it is.
There are three ways of handling your use case, let's start with the worst one.
A stateful web application
If you have loaded data into a Pojo from some data source and you want to re-use the Pojo between multiple requests, what you are trying to do is to implement some kind of client-state on the server, such as a cache. Web applications have been developed in this way for long time and this was the source of major bugs and errors. What happens if the underlying account data in the database is updated between one http request and the following? Your client won't see it, because it use cached data. Additionally, what happens when the user performs a back in his browser? How do you get notified on the server side so you keep track of where the user is in his navigation flow? For these and others reasons, Play! is designed to be stateless. If you are really into web applications, you probably need to read about what is the REST architectural style.
A stateless web application
In a stateless web applications, you are not allowed to keep data between two http requests, so you have two ways to handle it:
Generate the user interface in a single shot
This is the approach which you can use when your account data is reduced. You embed all the necessary data from each account into your page and you generate the view, which you keep hidden and you show only when the user clicks. Please note that you can generate the HTML on the server side and with Javascript makes only certain part of your DOM visible, or just transfer a JSON representation of your accounts and use some kind of templating library to build the necessary UI directly on the client
Generate the user interface when required
This approach becomes necessary when the account data structure contains too many informations, and you don't want to transfer all this information for all the accounts on the client at first. For example, if you know the user is going to be interested in seeing the details only of very few accounts, you want to require the details only when the user asks for it.
For example, in your list of accounts you will have a button associated with each account, called details and you will use the account id to send a new request to the server.
#(accounts: models.domain.AccountList)
#titlebar = {<p>some html</p>}
#content = {
#for(account <- accounts) {
<p>#account.name <button class="details" href="#routes.Controllers.account(account.id)">details</button></p>
}
}
Please note that you can also generate the user interface on the client side, but you will still need to retrieve it from the server the data structures when the user clicks on the button. This will ensure that the user retrieves the last available state of the account.
Old answer
If your goal is to reuse your views, Play views are nothing else then Scala classes, so you can import them:
#import packagename._
and then you use it in another template:
#for(account <- accounts) {
#account(account)
}
The question reveals a misunderstanding of play framework templates. When compiling the play project the template code is transformed to html, css and javascript.
You can not "invoke"/link another template showing the account transactions from a href attribute of your Account row. However, you can do any of the following:
In case you have loaded all transactions from all accounts to the client in one go: extend the template to generate separate <div> sections for each account showing the transactions. Also generate javascript to 1) hide the overview div and 2) show the specific transaction div when clicking on one of the accounts in the overview. Please see the knockout library proposed by Edmondo1984 or the accordion or tabs in twitter bootstrap.
In case you only load the account overview from the server. Generate a link such as this one href="#routes.Controllers.account(account.id)" (see Edmondo1984 answer) and make another template to view this data.
Since the question concerned a case in which you got all data from the server, go by option 1.

Tapestry 5 - Dynamically generate URL of file in web app context folder in Java code

I am displaying a static image asset inside a component, and I don't know until runtime what that image should be, so I need to dynamically generate the URL. These images all live in webapp/images/
The documentation I found is not very clear on how to handle this usecase, but after playing around I figured out I can construct the URL dynamically in the component template like so:
<img src="${context:img/score/overall}/${imageFilename}" />
Then put the logic for which image to display in the component class file:
public String getImageFilename() {
// decide which image to display and return the filename
}
So this works, but it's not the cleanest solution. I don't really want to concatenate the URL base to the filename inside the template - I'd much rather construct the entire URL in the component class, like so:
<img src="${imageUrl}" />
and
public String getImageURL() {
// build URL somehow like "context:" + "filePath" in template
}
So my question is: Is there a Java code equivalent of context: ... in the template that simply produces a String base URL for the web appl context folder that I can append my file path to?
I can see some obvious hacky ways of doing it from reading the docs, like manually constructing the base URL using the scheme described, or injecting a known static image as an Asset from the web app context folder and calling toClientURL() to extract the base URL. But it seems like there must be a nice built-in way to do this in Java, especially since it's freely available to use in a template expansion.
But google as I might, I can't seem to find how to do this anywhere!
I think this should do the trick for you. (disclaimer: I have not tested it)
#Inject
private AssetSource assetSource;
#Inject
private Locale locale;
public String getImageURL() {
URL assetUrl = assetSource.getContextAsset("img/score/overall/" + getImageFilename(), locale).toURL();
return assetUrl.toString();
}
Edit: Updated to reflect Howards comment

Scala Lift - Reading a file from "/resources/toserve"

I'm attempting to provide a StreamingResponse for files stored under Lifts resources/toserve directory, in order to authorize access for different users.
I can access an image for example with:
localhost:8080/classpath/images/test.jpg
But when I try and actually read the file using scala I keep getting file not found exceptions:
val file = new java.io.FileInputStream("/classpath/images/test.jpg")
Is there a specific method to reading files located on classpath?
Thanks in advance, much appreciated :)
To read resources from the toserve-directory you need to do a call like
LiftRules.getResource("/toserve/images/test.jpg")
If you try to use 'classpath' instead of 'toserve' you will receive an empty box.
By default, Lift uses two different path-prefixes to locate resources either programmatically within the server or through a link-element from HTML. For the former, you will use the 'toserve'-prefix, for the latter the 'classpath'-prefix.
This behavior is specified in the objects net.liftweb.http.LiftRules and net.liftweb.http.ResourceServer. In particular, you can there specify (i.e. replace) the path to the resources. The relevant code is:
/** (from net.liftweb.http.ResourceServer)
* The base package for serving resources. This way, resource names can't be spoofed
*/
var baseResourceLocation = "toserve"
You might also want to look at the following method in LiftRules, which allows you to redefine the name used to serve resources through the server:
/** (from net.liftweb.http.LiftRules)
* The path to handle served resources
*/
#volatile var resourceServerPath = "classpath"
If you wish to use the same prefix to refer both to resources you can use either (or both) of these settings to achieve your purpose.
Have you tried:
LiftRules.getResource("/classpath/images/test.jpg")
That should return a java.net.URL to the item you are looking for.
This may also have more information on what you are looking to do: http://exploring.liftweb.net/master/index-9.html#lst:streaming-download

How do I overwrite the URL in an IE address bar using RFT?

I need to execute the following steps:
1. Start an IE browser window and open a URL (Done using StartBrowser(final string URL)
2. Start a session (done by logging in)
3. Now, I want to enter a different URL in the same browser window which has the same session.
My question is related to Step 3. How can I overwrite the URL in the existing IE window.
Note: I am using a keyword driven framework written in java.
From the IBM RFT online help: You can use the loadURL() method of the browser object.
If you do not have the browser object already 'learned' into your object map, just record a click on the browser toolbar. Then you can modify that line to be Browser_htmlBrowser().loadURL("http://stackoverflow.com");
Thanks Tom. I agree that loadURL has the implementation to do what I need.
There is one more aspect that may interest others looking at this question, i.e. the way the appropriate browser object is captured. Obviously the easist way is to use the RFT record and click way, and use the appropriate recognition properties or the other way is to implement it is find the existing browseron the fly when the method is called irrespective of recognistion properties etc which may be more useful for some scenarios or frameworks, like it is done below.
RootTestObject root = getRootTestObject();
TestObject[] testobj = root.find(atDescendant(".class", "Html.HtmlBrowser"));
BrowserTestObject bto;
bto = new BrowserTestObject(testobj[0]);
bto.loadUrl(curParamOne);

Categories

Resources