best approach to implement getRealPath() - servlets

I am working on struts 2.0 . I am designing a web application.
I am using Jasper Report in my application. I want to access the *.jrxml files in my action class. I don't want to give hard coded path to the files. So to get the path dynamically I googled it and got the solution that I can get the path using getRealPath() method. But I found two implementation of doing this:
Using HttpSession to get object of ServletContext and using the getRealPath() method of the ServletContext object.
Like this:
HttpSession session = request.getSession();
String realPath = session.getServletContext().getRealPath("/");
The second approach to do it directly using the static method getServletContext() of ServletActionContext. And then we can get the real path of the application using the getRealPath() method.
Like this:
String realPath = ServletActionContext.getServletContext().getRealPath("/");
Please tell me, is there any difference between the above two and also please tell me whether there is any other way to get the path?

Neither is "better", really, and I'd argue that neither is particularly good, either.
I might try getting the context path in an initialization servlet and stick it into the application context, then make your action(s) ApplicationAware and retrieve the value from the map.
This has the added benefit of aiding testability and removing the static references in the action.
That said, I see zero reason to go through the extra mechanics of your first approach: it adds a lot of noise for no perceivable benefit; I'm not even sure why it wuld be considered.
I'd also be a little wary of tying your actions to a path like this unless there's a real need, what's the specific use? In general you shouldn't need to access intra-app resources by their path.

Related

What is the point of #WebInitParam?

#WebInitParam is an annotation that goes at class level.
It defines initialization parameters for the servlet.
I would like to know, what is the difference between doing this and using static variables, and why do it the #WebInitParam way rather than using statics?
What does defining k/v pairs as #WebInitParams allow you to do that you couldn't do if you declared static variables instead?
I have looked and all I can find is a million people saying how to define #WebInitParams. Well yes that's the easy bit. It's what I can do with that that is really what is of interest.
Thanks very much.
From a "raison d'etre" perspective, the annotation exists as a better design and architecture alternative to just peppering a class with static fields. #WebInitParam is a self-documenting approach to the initialization parameters a servlet or filter class needs, available via web.xml as well. It serves this purpose for the end developers as well as the JavaEE platform as a whole.
Think about it this way: in a vanilla project, you have the option of hardcoding a bunch of parameters in the class as static fields, or defining the same parameters in a property file. Which would you pick? Under what circumstances?
From a purely functional angle, apart from the function of using the annotation to override defaults set in web.xml, one other major reason is that you will sometimes need to get a hold of those initialization parameters from another component in your application. Using the annotation essentially increases the visibility of the parameter. In JSF for example, the API allows you to retrieve FacesServlet initialization parameters with:
//get all the parameters
FacesContext.getCurrentInstance().getExternalContext().getInitParameterMap()
//get a specific parameter
FacesContext.getCurrentInstance().getExternalContext().getInitParameter("aParameter");
In JSF-2.3 , it gets even more convenient with the following CDI-enabled injection:
#InitParameterMap Map<String,String> servletParameterMap;
Bear in mind that because it's CDI, it means this facility is available throughout the JavaEE platform, not just in web applications/JSF.
It's going to be a hassle to retrieve init parameters if the only mechanism available is a static field in the servlet class - you'll need to obtain an instance of the filter or servlet to get the static fields in it.
Separately, one could make the argument that maybe one should favour context-params over servlet-params because then, you get even more flexibility that isn't tied to any given servlet. That's a separate matter entirely :)

Alfresco Java backed web-script lookup by cmis:objectId

I am writing my first java-backed webscript for Alfresco community edition. I am implementing document properties / preview service, and I take a parameter which is the cmis:objectId of the document in question. I'm having trouble getting started because I haven't been able to access the document based on the cmis id.
What is the best way to get a document (NodeRef?) based on the cmis:objectId when operating server-side in a web-script controller? I see Jeff Potts' great examples on how to implement web scripts, but the mixing of the Java API and CMIS concepts has me stuck. Should I just use the search service and find the object based on the cmis:objectId property? Any pointers appreciated.
Well, the answer is a little ugly, but hopefully this helps someone...
A good way to look up the NodeRef using an 'opaque' objectId should be to use CMISServices, obtained from the registry in your java backed web script, i.e.
docRef = registry.getCMISService().getLatestVersion(docIdStr, false);
Unfortunately, there's a bug in the Alfresco code (or so it seems to me, admittedly a bit of a newbie). The alfresco CMISServicesImpl.getLatestVersion() uses a getObject() method under the covers. That method takes an objectId String as a parameter, but then strips off the version information at the end (i.e. the ";1.0" part of the objectId) and then checks to see if the remaining string is a valid NodeRef. In doing so, it checks it against this pattern (in NodeRef.java):
private static final Pattern nodeRefPattern = Pattern.compile(".+://.+/.+");
If the validation fails, you get a CMISInvalidArgumentException, with a message that xxxxx "is not an object ID".
So, to make a long story short, when I call the web script using a parameter for the objectId like this:
29ea5a16-12a8-497d-aad3-f43969e8a672;1.0
I get the CMIS exception. But, if I call the method with an objectId parameter that looks like this:
workspace://SpacesStore/29ea5a16-12a8-497d-aad3-f43969e8a672;1.0
... then, the "CMIS" lookup succeeds and I get my desired NodeRef back. Of course, all that the CMIS services are doing under the covers is stripping off the ";1.0" from the object ID, treating it as a NodeRef string, and doing the lookup using that.
In other words, you can't do it the right way in 4.2. The best thing to do is as #Gagravarr says and tweak your own objectId string to turn it into a NodeRef. Hopefully it's fixed in 5.x.

Asp.net MVC RouteBase and IoC

I am creating a custom route by subclassing RouteBase. I have a dependency in there that I'd like to wire up with IoC. The method GetRouteData just takes HttpContext, but I want to add in my unit of work as well....somehow.
I am using StructureMap, but info on how you would do this with any IoC framework would be helpful.
Well, here is our solution. Many little details may be omitted but overall idea is here. This answer may be a kind of offtop to original question but it describes the general solution to the problem.
I'll try to explain the part that is responsible for plain custom HTML-pages that are created by users at runtime and therefore can't have their own Controller/Action. So the routes should be either somehow built at runtime or be "catch-all" with custom IRouteConstraint.
First of all, lets state some facts and requirements.
We have some data and some metadata about our pages stored in DB;
We don't want to generate a (hypothetically) whole million of routes for all of existing pages beforehand (i.e. on Application startup) because something can change during application and we don't want to tackle with pushing the changes to global RouteCollection;
So we do it this way:
1. PageController
Yes, special controller that is responsible for all our content pages. And there is the only action that is Display(int id) (actually we have a special ViewModel as param but I used an int id for simplicity.
The page with all its data is resolved by ID inside that Display() method. The method itself returns either ViewResult (strongly typed after PageViewModel) or NotFoundResult in case when page is not found.
2. Custom IRouteConstraint
We have to somewhere define if the URL user actually requested refers to one of our custom pages. For this we have a special IsPageConstraint that implements IRouteConstraint interface. In the Match() method of our constraint we just call our PageRepository to check whether there is a page that match our requested URL. We have our PageRepository injected by StructureMap. If we find the page then we add that "id" parameter (with the value) to the RouteData dictionary and it is automatically bound to PageController.Display(int id) by DefaultModelBinder.
But we need a RouteData parameter to check. Where we get that? Here comes...
3. Route mapping with "catch-all" parameter
Important note: this route is defined in the very end of route mappings list because it is very general, not specific. We check all our explicitly defined routes first and then check for a Page (that is easily changeable if needed).
We simply map our route like this:
routes.MapRoute("ContentPages",
"{*pagePath}",
new { controller = "Page", action = "Display" }
new { pagePath = new DependencyRouteConstraint<IsPageConstraint>() });
Stop! What is that DependencyRouteConstraint thing appeared in mapping? Well, thats what does the trick.
4. DependencyRouteConstraint<TConstraint> class
This is just another generic implementation of IRouteConstraint which takes the "real" IRouteConstraint (IsPageConstraint) and resolves it (the given TConstraint) only when Match() method called. It uses dependency injection so our IsPageConstraint instance has all actual dependencies injected!
Our DependencyRouteConstraint then just calls the dependentConstraint.Match() providing all the parameters thus just delegating actual "matching" to the "real" IRouteConstraint.
Note: this class actually has the dependency on ServiceLocator.
Summary
That way we have:
Our Route clear and clean;
The only class that has a dependency on Service Locator is DependencyRouteConstraint;
Any custom IRouteConstraint uses dependency injection whenever needed;
???
PROFIT!
Hope this helps.
So, the problem is:
Route must be defined beforehand, during Application startup
Route's responsibility is to map the incoming URL pattern to the right Controller/Action to perform some task on request. And visa versa - to generate links using that mapping data. Period. Everything else is "Single Responsibility Principle" violation which actually led to your problem.
But UoW dependencies (like NHibernate ISession, or EF ObjectContext) must be resolved at runtime.
And that is why I don't see the children of RouteBase class as a good place for some DB work dependency. It makes everything closely coupled and non-scalable. It is actually impossible to perform Dependency Injection.
From now (I guess there is some kind of already working system) you actually have just one more or less viable option that is:
To use Service Locator pattern: resolve your UoW instance right inside the GetRouteData method (use CommonServiceLocator backed by StructureMap IContainer). That is simple but not really nice thing because this way you get the dependency on static Service Locator itself in your Route.
With CSL you have to just call inside GetRouteData:
var uow = ServiceLocator.Current.GetService<IUnitOfWork>();
or with just StructureMap (without CSL facade):
var uow = ObjectFactory.GetInstance<IUnitOfWork>();
and you're done. Quick and dirty. And the keyword is "dirty" actually :)
Sure, there is much more flexible solution but it needs a few architectural changes. If you provide more details on exactly what data you get in your routes I can try to explain how we solved our Pages routing problem (using DI and custom IRouteConstraint).

Looking for a good technique for storing email templates

I am building a site in which we are making moderate use of email templates. As in, HTML templates which we pass tokens into like {UserName}, {Email}, {NameFirst}, etc.
I am struggling with where to store these, as far as best practice goes. I'll first show the approach I took, and I'd be really excited to hear some expert perspective as a far as alternate approaches.
I created HTML templates in a folder called /Templates/.
I call a static method in my service layer, which takes in the following arguments:
UserName
UserID
Email
TemplatePath ("~/Templates")
Email Subject
Within the service layer I have my static method SendUserEmail() which makes use of a Template class - which takes a path, loads it as a string, and has a AddToken() Method.
Within my static SendUserEmail(), I build the token list off of the method signature, and send the email.
This makes for a quite long method call in my actual usage, especially since I am calling from the web.config the "TemplatePath", and "Email Subject". I could create a utility that has a shorter method call than the ConfigurationManager.AppSettings, but my concern is more that I don't usually see method signatures this long and I feel like it's because I'm doing something wrong.
This technique works great for the emails I have now, which at the most are using the first 3 tokens. However in the future I will have more tokens to pass in, and I'm just wondering what approach to take.
Do I create methods specific to the email needing to be sent? ie. SendNewUserRegistration(), SendMarketingMaterial(), and each has a different signature for the parameters?
I am using ASP.NET Membership, which contains probably the extend of all the fields I'll ever need. There are three main objects, aspnet_User, aspnet_Mebership and aspnet_profile. If it was all contained in one object, I would have just passed that in. Is there performance concerns with passing in all 3, to get all the fields I need? That is versus just passing in aspnet_User.UserID, aspnet_User.Email, etc?
I could see passing in a dictionary with the token entries, but I'm just wondering if that is too much to ask the calling page?
Is there a way to stick these in a config file of it's own called Templates.config, which has tags like -
<Templates>
<EmailTemplate Name="New User Registration">
<Tokens>
<UserName>
<UserID>
<Email>
</Tokens>
<Message Subject="Hi welcome...">
Hi {UserName}...
</Message>
</EmailTemplate>
</Templates>
I guess the main reason I'm asking, is because I'm having a hard time determining where the responsibility should be as far as determining what template to use, and how to pass in parameters. Is it OK if the calling page has to build the dictionary of TokenName, TokenValue? Or should the method take each in as a defined parameter? This looks out of place in the web.config, because I have 2 entries for and , and it feels like it should look more nested.
Thank you. Any techniques or suggestions of an objective approach I can use to ask whether my approach is OK.
First of all I would like to suggest you to use NVelocity as a template engine. As for main problem I think you can create an abstract class MailMessage and derive each one for every needed message (with unique template). So you will use this like following:
MailMessage message = new UserRegistrationMessage(tokens);
//some code that sends this message
Going this way you force each concrete XXXMessage class to be responsible for storing a template and filling it with the given tokens. How to deal with tokens? The simpliest way is to create a dictionary before passing it to the message, so each concrete message class will know how to deal with passed dictionary and what tokens it should contain, but you also need to remember what tokens it should contain. Another way (I like it more) is to create a general abstract type TokenSet and a derived one for every needed unique set of tokens. For example you can create a UserMessageTokenSet : TokenSet and several properties in it:
UserNameToken
SomeUserProfileDataToken
etc. So using this way you will always know, what data you should set for each token set and
UserRegistrationMessage will know what to take from this tokenSet.
There are a lot of ways to go. If you will describe you task better I think I will try suggest you something more concrete. But general idea is listed above. Hope it helps =)

Is there any way to use XmlSiteMapProvider within WinForm/Console/VSTest application?

I wonder whether there is a workaround for using the standard XmlSiteMapProvider within a non asp.net application, like WinForm/Console or, in my case, VS Unit Test one.
The following code fails, because it cannot create a path to the .sitemap file inside a private GetConfigDocument method.
XmlSiteMapProvider provider = new XmlSiteMapProvider();
NameValueCollection providerAttributes = new NameValueCollection();
providerAttributes.Add("siteMapFile", "Web.sitemap");
provider.Initialize("XmlSiteMapReader", providerAttributes);
provider.BuildSiteMap();
I feel the right solution is to write another provider.
I do not see why not. It is just a provider that implements an interface. You may not need many of the features, but you can access the API for what it provides you. Your WinForms screens can simply use the Urls for identification so that you can determine your place in the hierarchy.
What you may have to do is create a custom implementation of the provider because it will use the HttpContext to get the Url of the current web request to identify current placement while you will need to get that value differently. That is what could be tricky because your WinForm application could be displaying multiple windows at time. If you know there is only one window showing at a time you could use a static value which is set prior to accessing the SiteMap API.
Now you have to question the value of using an API if you have to do all of the work. There may not be enough benefit to make it worthwhile.

Resources