We have some configuration-store classes like this:
public class Configuration {
private static final Map<DocType, Map<ReportType, Template>> templates = new HashMap<>();
static {
Map<ReportType, Template> docZeroTemplates = new HashMap<>();
docZeroTemplates.put(REPORT_ZERO, new Template("/templates/ReportZero.jrxml", ReportZeroSource.class));
docZeroTemplates.put(REPORT_ONE, new Template("/templates/ReportOne.jrxml", ReportOneSource.class));
templates.put(DocType.DOC_ZERO, docZeroTemplates);
}
}
Advantages:
Refactoring and navigation support provided by IDE.
Disadvantages:
I'm not sure, it looks like something wrong.
I'm not even sure, that it should be called configuration.
Should I replace such classes by XML? Like this:
<configuration>
<document type="document0">
<reports>
<report type="report0">
<path>/templates/document0/report0.jrxml</path>
<source>org.company.report.ReportZero</source>
</report>
</reports>
</document>
</configuration>
Related
i had some problem showing images retrieved by my db.
View caller:
<p:graphicImage value="#{appController.image}" height="200 px" >
<f:param name="oid" value="#{item.oid}" />
</p:graphicImage>
Controller:
#Named("appController")
#ApplicationScoped
public class AppController {
#Inject
private MultimediaFacade multimediaFacade;
public StreamedContent getImage() throws IOException {
System.out.println("getting image")
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("oid");
int oid=Integer.parseInt(imageId);
System.out.println(oid);
Multimedia image = multimediaFacade.find(oid);
System.out.println(Arrays.toString(image.getFileBlob()));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getFileBlob()));
}
}
}
this code shows nothing and it looks like the method is never called (never print in console)!
after days of trial changing the scope, i tried to use #ManagedBean instead of #Named, and it works!!!
can someone explain me why this work only with #ManagedBean and not with #Named?
Check that you have javax.enterprise.context.ApplicationScoped in imports.
If you have a different import for #ApplicationScoped (e.g. javax.faces.bean.ApplicationScoped), then you need to configure CDI to discover all beans instead of only those with CDI annotations (which is the default)
To tun discovery for all beans, either add empty beans.xml into WEB-INF directory, or if you already have beans.xml there, add bean-discovery-mode="all" into the <beans> element, like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
</beans>
I am trying to create my own Html helper that will allow me to reuse some functionality across any web application. If I wanted to reuse this control in a single wep app I could create a .cshtml file and call it via the Html.Partial("") method and pass in a Model.
However as I have a class library project for my custom Html helpers I am creating the html with a string builder like this simplified version
StringBuilder htmlBuilder = new StringBuilder("<div class='myClass'>")
foreach(var item in MyItems)
{
htmlBuilder.Append($"item : {item.Name}");
}
htmlBuilder.append("</div>");
This makes it a pain to maintain especially as my control gets more features.
Is there a recommended way to leverage the razor engine where I can write the html in a .cshtml file with a model and then generate the html instead of using a string builder?
Yes. You can use a templated HTML helper to separate your view (HTML elements) from your model.
However, the downside is that you generally must put the templates either in the /Views/Shared/DisplayTemplates folder or a /DisplayTemplates folder inside of the view folder that represents the current controller. In the latter case, you can only use the template inside of that specific folder. It is possible to make a custom view engine that will pull the default templates as resources of a DLL file - see the MvcSiteMapProvider project for an example view engine implementation.
Example Templated HTML Helper
public class MyHelperModel
{
public string Title { get; set; }
public string Body { get; set; }
}
// Extension Methods for HTML helper
public static class MyHelperExtensions
{
public static MvcHtmlString MyHelper(this HtmlHelper helper, string title, string body)
{
return MyHelper(helper, title, body, null);
}
public static MvcHtmlString MyHelper(this HtmlHelper helper, string title, string body, string templateName)
{
// Build the model
var model = BuildModel(title, body);
// Create the HTML helper for the model
return CreateHtmlHelperForModel(helper, model)
.DisplayFor(m => model, templateName);
}
private static MyHelperModel BuildModel(string title, string body)
{
// Map to model
return new MyHelperModel
{
Title = title,
Body = body
};
}
private static HtmlHelper<TModel> CreateHtmlHelperForModel<TModel>(this HtmlHelper helper, TModel model)
{
return new HtmlHelper<TModel>(helper.ViewContext, new ViewDataContainer<TModel>(model));
}
}
public class ViewDataContainer<TModel>
: IViewDataContainer
{
public ViewDataContainer(TModel model)
{
ViewData = new ViewDataDictionary<TModel>(model);
}
public ViewDataDictionary ViewData { get; set; }
}
MyHelperModel.cshtml
The default conventions use a display template with the same name as the model when no templateName argument is passed (or it is null). Therefore, this will be our default HTML helper format. Note that you could instead just hard-code the HTML elements into the helper in the default case instead of using a template (or going the extra mile of creating a view engine).
As mentioned above, this should be in the /Views/Shared/DisplayTemplates/ folder, but you could make a custom view engine to pull the default template from a DLL.
#model MyHelperModel
<h3>#Model.Title</h3>
<p>#Model.Body</p>
CustomHtmlHelperTemplate.cshtml
Here is a named template that can be used within the application to change the HTML elements applied to the HTML helper.
As mentioned above, this should be in the /Views/Shared/DisplayTemplates/ folder, but you could make a custom view engine to pull the default template from a DLL.
#model MyHelperModel
<h1>#Model.Title</h1>
<p><i>#Model.Body</i></p>
Usage
#Html.MyHelper(
"This is the default template",
"This is what happens when we don't pass a template name to the HTML helper.")
#Html.MyHelper(
"This is a custom template",
"This is a custom template with different HTML elements than the default template.",
"CustomHtmlHelperTemplate")
NOTE: To ensure the helpers are available in the views, you need to add the namespaces in the /Views/Web.config file at <system.web.webPages.razor><pages><namespaces>.
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<!-- Add your namespaces here -->
<add namespace="MyProject.HtmlHelperNamespace" />
<add namespace="MyProject.HtmlHelperNamespace.Models" />
</namespaces>
</pages>
</system.web.webPages.razor>
You can maintain and generate at runtime the output of a Razor View / PartialView (cshtml), using this code:
public static string GetViewPageHtml(Controller controller, object model, string viewName)
{
ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
if (result.View == null)
throw new Exception(string.Format("View Page {0} was not found", viewName));
controller.ViewData.Model = model;
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (System.Web.UI.HtmlTextWriter output = new System.Web.UI.HtmlTextWriter(sw))
{
ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, controller.ViewData, controller.TempData, output);
result.View.Render(viewContext, output);
}
}
return sb.ToString();
}
You call it like this (from a Controller)
string result = GetViewPageHtml(this, viewModel, "~/Views/Home/Index.cshtml");
I've been trying to insert a XML file into mongoDB with camel and I can't manage to make it work.
I've followed this tutorial for the first steps:
http://www.pretechsol.com/2014/09/apache-camel-mongodb-component-example.html
In my route, I convert it in JSON then use 'convertBodyTo(string.class) for mongo to recognize the file.
The code works well with regular route (sending the file to another folder for example). But when I run it for mongoDB, all I get in the console is my Process message again and again with my databased never being filled.As I don't receive any error message, I don't know how to find where the problem come from.
The mongoDB name, ip, users, password have been already checked multiple times.
I would be very grateful if someone could help me on this one. Here is the files I am using. (I will spare you the process file).
camel-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="myDb" class="com.mongodb.Mongo">
<constructor-arg index="0">
<bean class="com.mongodb.MongoURI">
<constructor-arg index="0"
value="mongodb://username:password#192.168.3.29:27017/db" />
</bean>
</constructor-arg>
</bean>
<bean id="mongodb" class="org.apache.camel.component.mongodb.MongoDbComponent"></bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="camelRoute" />
</camelContext>
<bean id="camelRoute" class="infotel.camel.project01.CamelRoute" />
Here is my RoutingFile:
#Component
public class CamelRoute extends SpringRouteBuilder {
final Processor myProcessor = new MyProcessor();
final Processor myProcessorMongo = new MyProcessorMongo();
final XmlJsonDataFormat xmlJsonFormat = new XmlJsonDataFormat();
#Override
public void configure() {
xmlJsonFormat.setForceTopLevelObject(true);
from("file:xml_files?noop=true").marshal(xmlJsonFormat).convertBodyTo(String.class).process(myProcessorMongo)
.to("mongodb:myDb?database=test_bignav&collection=doc&operation=insert");
}
}
And finally here is my main:
public class MyMain {
public static void main(String[] args) throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("META-INF/spring/camel-context.xml");
}
}
Thanks a lot.
Edit:
Here is MyProcessorMongo edited to get the error:
public class MyProcessorMongo implements Processor{
public void process(Exchange exchange) throws Exception {
System.out.println("\n file transfered to mongo: "+ exchange.getIn().getHeader("CamelFileName"));
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class).printStackTrace();
}
}
Enable tracing with trace="true":
<camelContext trace="true" xmlns="http://camel.apache.org/schema/spring">
Dirty but quick, to get the error you can add this to you configure() method before your from :
.onException(Exception.class).handled(true).process(new Processor() {
#Override
public void process(Exchange exchange) {
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class).printStackTrace();
}
})
The handled(true) prevents your message from being processed again and again.
thanks for your help I have been able to get the error message.
The problem actually came from mongoDB itself and not camel or code. With the change on users the connection works and I'm able to insert document inside a collection.
Remove the ".process(myProcessorMongo)" from route configuration . Input xml-> json conversion->string conversion -> Mongodb. Above route will work. And you are passing the exchange object to myProcessorMongo but Out message is null so nothing will be inserted into MongoDB . Put exchange.getOut().getBody(); in the myProcessorMongo and print it.If its coming as null u have to get the input message from exchange Obj and set it back it in to Out message property in the exchange Object.
Consider the following scenario
I have a MVC5. I would like to have a base view with some dependencies as:
public class BasicView<T> : WebViewPage<T>
{
public IResourceService ResourceService { get; set; }
public override void Execute()
{
}
}
Then in the webconfig....
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="BasicView">
The property is never injected :(
when I use the same dependency on a regular constructor, works without problems.
What am I missing here? Windsort documentation says the container will try to resolve that kind of Properties.
Windsor does not inject into your views because it does not own the view creation process.
You have to use Windsor as service locator in this scenario. See this answer to find out how to use it.
I have an ASP.NET 3.5 SP1 web application that uses a custom JavaScriptConverter. The code used to work at some time in the past, but has stopped working. I do not know what changes have happened in the middle server side. The problem we are seeing now is that the converter is not being invoked, so we are getting errors that System.Data.DataRow cannot be serialized.
The following is the relevant portion of web.config:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview" />
<add name="DataRowConverter" type="WebUI.DataRowConverter, WebUI.DataRowConverter, Version=1.1.0.323, Culture=neutral" />
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
A trimmed version of the class is as follows (trimmed only to avoid wasting space on unnecesary implementation):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Web.Script.Serialization;
namespace WebUI {
public class DataRowConverter : JavaScriptConverter {
private ReadOnlyCollection<Type> _supportedTypes = new ReadOnlyCollection<Type>(new Type[] { typeof(DataRow) });
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
// stuff
return dr;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
// stuff
return dictionary;
}
public override IEnumerable<Type> SupportedTypes {
get {
return this._supportedTypes;
}
}
}
}
What seems to happen is that the class is indeed being loaded (if we take it out of web.config and the project references, no breakpoints are available; put it back into web.config and copy the DLL/PDB by hand or add it to the project, breakpoints are available), but it's not being used propertly. No breakpoint anywhere in the class is hit, and no exceptions (including one thrown in a constructor added to see what happens) are thrown. It seems like the class is being loaded but never called.
This is on IIS 7.5 and IIS 7.0 in Integrated mode, if it matters.
Anyone have any ideas?
OK, just in case anyone else hits this, when calling web services through the automatically generated test pages, the custom serializers are not invoked - they are bypassed. This is apparently by design.