I'm in the process of converting a classic ASP application to ASP.Net and have hit a brick wall to do with global variables (or page scope variables). As a note, the application is not a typical one in that it doesn't build HTML. Instead it gets AJAX requests and returns JSON strings, so as such doesn't use a lot of asp.net functionality. First time for a long time that googling hasn't lead me to an answer!
In the asp code we use a number of global variables defined in variables.asp, eg:
<%
dim lId
%>
This asp is then included in all pages. There are a number of other include files that reference these variables, along with the pages themselves.
For asp.net the closest I can find is to have variables.aspx:
<SCRIPT LANGUAGE="VBScript" RunAt="Server">
shared dim lId as integer
</SCRIPT>
However, I realise that this variable is much more 'global' than how it worked in .asp, and that it can cause threading issues etc, and that they effecitvely work like using the Application() object, which is not what I'm after.
Effectively what I need is to be able to declare a variable that can be referenced in other includes, and in the base page, whose scope/lifetime is only for the processing of that page.
At this stage, the only thing I can think of is to use Session variables, and to clear them at the end of each processing, but am dreading the work / issues of such a conversion
You could create a class in your asp.net project to store these static variables. If they are configuration parameters, they should go in the web.config file.
Looks like I might end up doing something like the following:
shared dim gv as New GlobalVariables
public class GlobalVariables
public property Id as integer
Get
Id = cint(HttpContext.Current.Items("id"))
End Get
set (ByVal aiValue as integer)
HttpContext.Current.Items("id") = aiValue
End Set
end property
end class
Then where ever I currently reference "lId", I need to replace with "gv.Id".
gv will still be global, but given it is looking in current.items I shouldn't have any thread issues.
Related
Is it possible to call a static method from a Thymeleaf textual template?
Official guide mentions that it should be possible to call a method like this:
<p th:text="${#myapp.translator.Translator#translateToFrench(textVar)}">Some text here...</p>
When I try to use it in my textual template (TemplateResolver's mode is set to TemplateMode.TEXT), I get a this exception:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "#java.lang.System#currentTimeMillis()" (template: "template.txt" - line 1, col 18)
Here is my sample template:
System millis: [(${#java.lang.System#currentTimeMillis()})]
After googling for a while, I also found this form of calling methods:
System millis: [(${T(java.lang.System).currentTimeMillis()})]
which fails with the same error.
What I need to do is somehow allow usage of a custom number formatter class from a template (functionality of the #numbers utility object is not rich enough for my case).
I can call methods on a non-static class by providing it as a context variable like this:
Some value: [(${formatter.format(someValue)})]
but it would be easier for me to use a static class without a need to explicitly adding it to each template's context.
BTW, I do not use Spring, just pure Thymeleaf.
Update
I should've spend more time to analyze the stack trace of the Thymeleaf exception I got.
It turns out, that the root cause of this behavior was the org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes is forbidden in this context exception, which is results from this change: https://github.com/thymeleaf/thymeleaf/issues/809
Downgrading to Thymeleaf 3.0.11 "fixes" it.
Now I'm looking for a solution to bypass this new Resctricted mode on the latest Thymeleaf (3.0.12 for the moment). I'm sure it's safe in my case, because I'm the only author of both code and templates.
An alternative would be to use the th:with attribute. It's a little more verbose, but still should allow you the same flexibility. (This works for me on 3.0.12.RELEASE.)
[# th:with="time=${#java.lang.System#currentTimeMillis()}"]System millis: [[${time}]][/]
https://github.com/thymeleaf/thymeleaf/issues/816#issuecomment-826401631 has extensive info on why this was done and possible workarounds. In your case, it will be best to add a model attribute in your controller and use that instead of calling the static method in the template.
#Controller
public class MyController {
public String myControllerMethod(Model model) {
model.addAttribute("time", System.currentTimeMillis());
return "name-of-the-thymeleaf-template";
}
}
and update your template to use:
System millis: [(${time})]
I've read on this blog about how to use resourceResolver properly. The author quotes
If you open a JCR session of a Sling ResourceResolver, you are also
responsible for closing it. On the other hand: If you get passed a
ResourceResolver or a Session object, do not call logout() or close()
on it.
I'm not able to grasp this concept, may be because of no code example in this case.
From what i know, i can get a ResourceResolver object via either request.getResourceResolver() in servlets, using #Reference SCR annotation in OSGi components, jsp's implicit resourceResolver object, using sling.getService() in jsp, and also via adapting to ResourceResolver object.
In all the ways of getting resourceResolver object, which ones should i close myself and what is the session associated with each of these objects ?
Think of it like a File resource.
if you open it, you are responsible for closing it
if you use a reference to the File, then it is not your responsibility to close it
Therefore, your code should open & close in the same scope.
If you obtain a resourceResolver FROM a resource, you did not open the resolver and you do not need to close it.
In the example from the blog, they generate a session from session = repo.loginAdministrative() (Repository no longer has this method); thus is responsible for calling session.logout() in the same scope (using the finally {...} block).
I am using angular ui grid. At first I implemented this in a controller and it works fine after all my customization. As I am using multiple grids I cannot write a long controller each time. So, I converted it to factory. I kept the common function in factory and column definition and data in controller. Now when I use this factory in more than 1 controllers, the last controller is overriding all others.
1) Is it correct to make this grid in a factory?
2) If yes how do I overcome this problem?
3) By using factory for this grid, my gridObj.gridApi.pagination.on is throwing error(gridObj is the singleton object that I am returning).
Any suggestion is welcome. Thanks a lot in advance.
You should use a Directive instead. Factories create a single Instant (see Angular Provider Documentation and wont create a private scope, which you need to not override your data.
Note: All services in Angular are singletons.
But Directives provide a private scope and create new instances every time they are called in HTML if you want them to.
//directive
scope: { // this option creates isolated scopes
something : '=',
},
I created a Plunkr showcasing a possible setup. For some more written details please see my answer from few days ago.
Your HTML might look like this afterwards
<my-grid options="all.firstOptions" class="grid"></my-grid>
Where my-grid is your directive and options="" are your special settings (and whatever else you wish to use in the directive). In your directive you declare the default settings and merge them with the special ones.
scope.gridOptions = {
data: scope.options.data, //private scoped from options : '=',
columnDefs: scope.options.colDef || defaultColDef, // optional setting or default setting
// ... some more default data
};
If you have any specific questions, let me know.
I want to output a value which is global in all the templates or even layout in Grails, like Django's context processor where you could render the context and use it as global variable in the templates.
Is there a concept like this in Grails? And, how can I use that in the layout?
I am not familiar with Django at all. Looked up Django's context processor in google, I think I get it. Basically it configures reusable data that gets injected into every template? Anyway, as far as I know nothing like that exists in Grails. You can try the following as a workaround.
Use ApplicationContext
Every view has access to the applicationContext. So make a service that holds all the data you need, let's say it is called fooService, and the data item you want is a field in the service called bar (could be a method too of course). Then in your view do ${applicationContext.fooService.bar}. Resource for accessing applicationContext in view: http://mrhaki.blogspot.com/2011/11/grails-goodness-get-grailsapplication.html.
Use your layout
I am not sure about this one, so use at your own risk. The top one is of course extremely verbose. It would be annoying to call that over and over again in different views. So instead, call it once and make it a variable in your layout with g:set. I think the variable will be available in every view that uses that layout.... but not sure. Here are the docs for g:set -> http://grails.org/doc/latest/ref/Tags/set.html.
If I didn't get what context processors do in python I am happy to try again...
I need a global variable that I can call from the templates.
I edited app_globals.py in lib directory to declare PATH_TO_IMAGES like this
class Globals(object):
"""Container for objects available throughout the life of the application.
One instance of Globals is created during application initialization and
is available during requests via the 'app_globals' variable.
"""
PATH_TO_IMAGES = ""
def __init__(self):
"""Do nothing, by default."""
pass
Now I can call from any template the image path like this
<img src="${g.PATH_TO_IMAGES}/${p.image}" />
The image path is stored inside a settings table on the app's database, but I can't initialize it from Globals declaration, i get this error:
sqlalchemy.exc.UnboundExecutionError:
Could not locate a bind configured on
mapper
Mapper|Settings|settings,
SQL expression or this Session
My guess is that database binding happens after Globals is initialized. So my questions is, which is the best place to initialize a global variable in TurboGears 2 and which is the best practice to that.
Just use a cached property:
class Globals(object):
"""Container for objects available throughout the life of the application.
One instance of Globals is created during application initialization and
is available during requests via the 'app_globals' variable.
"""
#property
def PATH_TO_IMAGES(self):
try:
return self._path_to_images
except AttributeError:
self._path_to_images = db_session.query(XXX) # Fill in your query here
return self._path_to_images
PS : your question is a generic Python question really. I suggest you read the official Python docs before posting other similar questions.
You probably need to create your own database connection to get this data from the database.
In SQLAlchemy terms, you'll want to create your own engine, session, etc. Just make sure to clean up after you're done.
I would probably do this in app_cfg.py using on_startup to get it into the config, and then stick it in the Globals object later on if you still need to.
You may set PATH_TO_IMAGES to it's definite value once the models are initialized. The sooner being at the end of the 'init_model' function declared in model/init.py.