Is there a way to configure Acknowledgements with Spring.NET?
In code it looks like this:
var msgQ = new MessageQueue(OrdersQueueName)
{
DefaultPropertiesToSend =
{
AcknowledgeType = AcknowledgeTypes.FullReachQueue |
AcknowledgeTypes.FullReceive,
AdministrationQueue = new MessageQueue(AckQueueName)
}
};
Could it be done with the ProductTemplate? Another way?
For me, this configuration worked:
<objects xmlns="http://www.springframework.net">
<!-- for http://stackoverflow.com/questions/3491152/configuring-acknowledgements-with-spring-net -->
<object name="orders" type="q3491152.MessageQueue, q3491152">
<property name="Name" value="orders-from-xml" />
<property name="DefaultPropertiesToSend">
<object type="q3491152.PropertiesToSend, q3491152">
<property name="AdministrationQueue" ref="anotherQ" />
<property name="AcknowledgeType"
expression="T(q3491152.AcknowledgeTypes).FullReachQueue or T(q3491152.AcknowledgeTypes).FullReceive" />
</object>
</property>
</object>
<object name="anotherQ" type="q3491152.MessageQueue, q3491152">
<property name="Name" value="anotherQ" />
</object>
</objects>
In this example I mocked the (apparently) relevant parts of the msmq classes.
I use an expression to get a bit-wise comparison on the enum.
If you register the AcknowledgeType with the Spring.Core.TypeResolution.TypeRegistry using TypeRegistry.RegisterType("AcknowledgeTypes", typeof(AcknowledgeTypes));, the expression further simplifies to:
<property name="AcknowledgeType"
expression="AcknowledgeTypes.FullReachQueue or AcknowledgeTypes.FullReceive" />
I've tested it with the following program, against Spring.NET 1.3.1:
using System;
using Spring.Context;
using Spring.Context.Support;
namespace q3491152
{
internal class Program
{
private static void Main(string[] args)
{
IApplicationContext ctx = new XmlApplicationContext("objects.xml");
var qFromCode = new MessageQueue
{
Name="orders-from-code",
DefaultPropertiesToSend =
{
AcknowledgeType = AcknowledgeTypes.FullReachQueue |
AcknowledgeTypes.FullReceive,
AdministrationQueue = new MessageQueue()
}
};
var qFromXml = (MessageQueue) ctx.GetObject("orders");
PrintQ(qFromCode);
PrintQ(qFromXml);
Console.ReadLine();
}
private static void PrintQ(MessageQueue q)
{
Console.WriteLine("Q: {0}; AcknowledgeType: {1}", q.Name, q.DefaultPropertiesToSend.AcknowledgeType);
}
}
public class MessageQueue
{
public MessageQueue()
{
DefaultPropertiesToSend = new PropertiesToSend();
}
public string Name { get; set; }
public PropertiesToSend DefaultPropertiesToSend { get; set; }
}
public class PropertiesToSend
{
public AcknowledgeTypes AcknowledgeType { get; set; }
public MessageQueue AdministrationQueue { get; set; }
}
[Flags]
public enum AcknowledgeTypes
{
None = 0,
FullReachQueue,
FullReceive
}
}
Which outputs:
Q: orders-from-code; AcknowledgeType: FullReachQueue, FullReceive
Q: orders-from-xml; AcknowledgeType: FullReachQueue, FullReceive
Related
In my demo project I set up data for a listview via EntityFrameworkCore FromRawSql
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Things03.Module.Functions;
namespace Things03.Module.BusinessObjects
{
[NavigationItem("OldWayUseRibbonInstead")]
[DomainComponent]
public class ThingFilterHolder
{
public ThingFilterHolder()
{
ThingFilter = new ThingFilter();
ApplyFilter();
}
[Browsable(false)]
[Key]
public int Id { get; set; }
public ThingFilter ThingFilter { get; set; }
public virtual List<Thing> Things { get; set; }
public void ApplyFilter()
{
var search = StringFunctions.SafeString(ThingFilter.Search);
var sql = $"select Id, Name from Things where Name like '%{search}%'";
var db = DataFunctions.MakeDbContext();
Things = db.Things.FromSqlRaw(sql).ToList();
}
}
}
I find the technique is very powerful.
However the Navigation actions are disabled and Refresh does not work.
I expect that this is because there is no underlying ObjectSpace that "knows" the listview collection.
The Next and Previous do enable if I add a record, but only for the added record.
If I enable diagnostics I see the following about the RecordsNavigationController
<Controller Name="RecordsNavigationController" FullName="DevExpress.ExpressApp.SystemModule.RecordsNavigationController" Active="True">
<ActiveList>
<Item Key="View is assigned" Value="True" />
<Item Key="View type is ObjectView" Value="True" />
<Item Key="PropertyEditor has ObjectSpace" Value="True" />
</ActiveList>
<Actions>
<Action ID="PreviousObject" Caption="Previous Record" TypeName="SimpleAction" Category="RecordsNavigation" Active="True" Enabled="False" AdditionalInfo="">
<ActiveList>
<Item Key="Controller active" Value="True" />
<Item Key="ByContext_RequireSingleObject" Value="True" />
<Item Key="ListView or root DetailView" Value="True" />
<Item Key="Editor doesn't support focused row selection." Value="True" />
</ActiveList>
<EnabledList>
<Item Key="ByContext_RequireSingleObject" Value="True" />
<Item Key="Can move to previous" Value="False" />
</EnabledList>
</Action>
<Action ID="NextObject" Caption="Next Record" TypeName="SimpleAction" Category="RecordsNavigation" Active="True" Enabled="False" AdditionalInfo="">
<ActiveList>
<Item Key="Controller active" Value="True" />
<Item Key="ByContext_RequireSingleObject" Value="True" />
<Item Key="ListView or root DetailView" Value="True" />
<Item Key="Editor doesn't support focused row selection." Value="True" />
</ActiveList>
<EnabledList>
<Item Key="ByContext_RequireSingleObject" Value="True" />
<Item Key="Can move to next" Value="False" />
</EnabledList>
</Action>
</Actions>
</Controller>
The detail view is opened by an action on the toolbar.
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Win;
using System.Linq;
using Things03.Module.BusinessObjects;
namespace Things03.Module.Win.Controllers
{
public class ThingFilterController : ViewController
{
SimpleAction actThingScreen;
public ThingFilterController() : base()
{
TargetViewNesting = Nesting.Root;
actThingScreen = new SimpleAction(this, "Things", "View");
actThingScreen.Execute += actThingScreen_Execute;
}
private void actThingScreen_Execute(object sender, SimpleActionExecuteEventArgs e)
{
var holder = new ThingFilterHolder();
var holderType = holder.GetType();
var viewId = Application.FindDetailViewId(holderType);
if (SwitchToViewIfOpen(Application, viewId)) return;
var os = Application.CreateObjectSpace(typeof(Thing)); // any valid type would have done
var detailView = Application.CreateDetailView(os, holder);
e.ShowViewParameters.CreatedView = detailView;
e.ShowViewParameters.TargetWindow = TargetWindow.NewWindow;
e.ShowViewParameters.NewWindowTarget = NewWindowTarget.MdiChild;
}
private bool SwitchToViewIfOpen(XafApplication application, string viewId)
{
if (!(application.ShowViewStrategy is WinShowViewStrategyBase strategy)) return false;
foreach (var win in strategy.Windows.ToArray())
{
if (win.View == null) continue;
if (!win.View.Id.Equals(viewId)) continue;
win.Show();
return true;
}
return false;
}
}
}
The fix was to populate the list via ObjectSpace
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Things03.Module.Functions;
namespace Things03.Module.BusinessObjects
{
[NavigationItem("OldWayUseRibbonInstead")]
[DomainComponent]
public class ThingFilterHolder
{
public ThingFilterHolder()
{
ThingFilter = new ThingFilter();
ApplyFilter();
}
[Browsable(false)]
[Key]
public int Id { get; set; }
public ThingFilter ThingFilter { get; set; }
public virtual List<Thing> Things { get; set; }
[Browsable(false)] public IObjectSpace ObjectSpace { get; set; }
public void ApplyFilter()
{
var search = StringFunctions.SafeString(ThingFilter.Search);
var sql = $"select Id, Name from Things where Name like '%{search}%'";
var db = DataFunctions.MakeDbContext();
var things1 = db.Things.FromSqlRaw(sql).ToList();
Things = new List<Thing>();
if (ObjectSpace == null) return;
foreach (Thing t in things1)
{
Thing t2 = ObjectSpace.GetObject<Thing>(t);
Things.Add(t2);
}
}
}
}
I was able to achieve this by adding an ObjectSpace property to the ThingFilterHolder and having the Action set the property.
I also had to override the refresh controller.
public class MyRefreshController : RefreshController
{
public MyRefreshController() : base()
{
}
protected override void Refresh()
{
var holder = View.CurrentObject as ThingFilterHolder;
holder.ApplyFilter();
View.Refresh();
base.Refresh();
}
}
and the Delete
public class MyDeleteController : DeleteObjectsViewController
{
public MyDeleteController() : base()
{
}
protected override void Delete(SimpleActionExecuteEventArgs args)
{
base.Delete(args);
View.ObjectSpace.CommitChanges();
}
}
When I try to the following LINQ Filter
var productsInfo = from product in productsElement.Descendants("product").Filter(rule)
from photo in product.Descendants("photo")
from parameter in product.Descendants("parameter")
let id = product.Attribute("id")
let addr = photo.Attribute("addr")
let name = parameter.Attribute("name")
select new { ID = id.Value, Addr = addr.Value, Name = name.Value };
I get the following error:
The given ruleset does not contain any rules with type
System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 (Error E106)
My rule:
<?xml version="1.0" encoding="utf-8"?><codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4"><rule id="09973a56-3d6a-4616-ae1c-40d0d17e95b9" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="testSlimWebRule.products, testSlimWebRule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" eval="true"><definition><condition type="equal"><property name="AllProducts.product.id" /><value type="numeric">1</value></condition></definition><format><lines /></format></rule></codeeffects>
The XML:
XDocument productsElement = XDocument.Parse(#"<products>
<AllProducts>
<product id='1'>
<photo addr='1.jpg'/>
<parameter name='name'/>
</product>
<product id='2'>
<photo addr='2.jpg'/>
<parameter name='Kenneth'/>
</product>
</AllProducts>
</products> ");
The products class generated using Visual Studio "Insert as XML class":
namespace testSlimWebRule
{
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class products
{
private productsAllProducts allProductsField;
/// <remarks/>
public productsAllProducts AllProducts
{
get
{
return this.allProductsField;
}
set
{
this.allProductsField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProducts
{
private productsAllProductsProduct productField;
/// <remarks/>
public productsAllProductsProduct product
{
get
{
return this.productField;
}
set
{
this.productField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProduct
{
private productsAllProductsProductPhoto photoField;
private productsAllProductsProductParameter parameterField;
private byte idField;
/// <remarks/>
public productsAllProductsProductPhoto photo
{
get
{
return this.photoField;
}
set
{
this.photoField = value;
}
}
/// <remarks/>
public productsAllProductsProductParameter parameter
{
get
{
return this.parameterField;
}
set
{
this.parameterField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProductPhoto
{
private string addrField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string addr
{
get
{
return this.addrField;
}
set
{
this.addrField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProductParameter
{
private string nameField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
}
}
The ASP.net part:
<rule:RuleEditor ID="ruleEditor" runat="server"
Mode="Filter"
ShowToolBar="false"
SourceAssembly="testSlimWebRule"
SourceType="testSlimWebRule.products" />
I have tried several combinations of setting the filter, but just can't find a solution.
What am I missing?
The Filter() extension takes a collection of objects and evaluates them against a given rule individually. The rule engine takes a type of an element of the collection and uses it to compile a lambda with a parameter of that type.
List<MyClass> list = new List<MyClass>();
list.Filter(rule);
In this example the rule is of type MyClass and it gets applied to each object in the list similar to:
Evaluator<MyClass> ev = new Evaluator<MyClass>(rule);
foreach (var item in list)
{
ev.Evaluate(item);
}
You may read more on CodeEffects documentation page: Rule-Based Data Filtering Using LINQ to Object Provider.
In your example you made few mistakes:
You generate classes for XML elements, but don't use them.
The auto-generated classes incorrectly map the AllProduct field. It is supposed to be an array of productsProduct.
You apply a filter to a collection of XElement objects but the rule has type testSlimWebRule.products. It should be XElement in this case.
The example below will demonstrate four possible options, with the first one being the best.
Main
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;
using CodeEffects.Rule.Core;
namespace testSlimWebRule
{
class Program
{
/* Output:
* Option A: 1, Bob, 1.jpg
* Option B: 1, Bob, 1.jpg
* Option C: 1, Bob, 1.jpg
* Option D: 2, Kenneth, 2.jpg
*/
static void Main(string[] args)
{
string xml =
#"<products>
<AllProducts>
<product id='1'>
<photo addr='1.jpg'/>
<parameter name='Bob'/>
</product>
<product id='2'>
<photo addr='2.jpg'/>
<parameter name='Kenneth'/>
</product>
</AllProducts>
</products>";
XDocument dom = XDocument.Parse(xml);
products products;
//You need to load auto-generated classes. I prefer serialization. You may parse XML elements individually.
using (var xmlReader = dom.CreateReader())
{
var serializer = new XmlSerializer(typeof(products));
products = (products)serializer.Deserialize(xmlReader);
}
string productsProductRule = File.ReadAllText("rule1.xml");
//A: Filter productsProduct[]; result is IEnumerable<productsProduct>.
//This rule evaluates objects of the productsProduct type.
var filteredProducts = products.AllProducts.Filter(productsProductRule);
foreach (var product in filteredProducts)
Console.WriteLine("Option A: {0}, {1}, {2}", product.id, product.parameter.name, product.photo.addr);
string xElementRule = File.ReadAllText("rule2.xml");
//B: Filter IEnumerable<XElement>; result is IEnumerable<XElement>.
//This rule evaluates objects of the XElement type.
var filteredElements = dom.Descendants("product").Filter(xElementRule);
foreach (var element in filteredElements)
Console.WriteLine("Option B: {0}, {1}, {2}", element.Attribute("id").Value, element.Element("parameter").Attribute("name").Value, element.Element("photo").Attribute("addr").Value);
//C: Filter IEnumerable<XElement>; result is IEnumerable<'a> (anonymous)
//This rule also evaluates objects of the XElement type.
var productsInfo = from product in dom.Descendants("product").Filter(xElementRule)
from photo in product.Descendants("photo")
from parameter in product.Descendants("parameter")
let id = product.Attribute("id")
let addr = photo.Attribute("addr")
let name = parameter.Attribute("name")
select new
{
ID = id.Value,
Addr = addr.Value,
Name = name.Value
};
foreach (var info in productsInfo)
Console.WriteLine("Option C: {0}, {1}, {2}", info.ID, info.Name, info.Addr);
string anonymousRule = File.ReadAllText("rule3.xml");
//D: Filter IEnumerable<'a>; result is IEnumerable<'a>
//This rule evaluates objects of the anonymous type 'a with properties ID, Addr, and Name.
var productsInfo2 = (from product in dom.Descendants("product")
from photo in product.Descendants("photo")
from parameter in product.Descendants("parameter")
let id = product.Attribute("id")
let addr = photo.Attribute("addr")
let name = parameter.Attribute("name")
select new
{
ID = id.Value,
Addr = addr.Value,
Name = name.Value
})
.Filter(anonymousRule);
foreach (var info in productsInfo2)
Console.WriteLine("Option D: {0}, {1}, {2}", info.ID, info.Name, info.Addr);
}
}
}
Auto-generated classes
You need re-paste your XML example to generate proper array fields. The one you have was generated with XML sample that only had one record. However to filter you need a collection.
using System;
namespace testSlimWebRule
{
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class products
{
private productsProduct[] allProductsField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("product", IsNullable = false)]
public productsProduct[] AllProducts
{
get
{
return this.allProductsField;
}
set
{
this.allProductsField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsProduct
{
private productsProductPhoto photoField;
private productsProductParameter parameterField;
private byte idField;
/// <remarks/>
public productsProductPhoto photo
{
get
{
return this.photoField;
}
set
{
this.photoField = value;
}
}
/// <remarks/>
public productsProductParameter parameter
{
get
{
return this.parameterField;
}
set
{
this.parameterField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsProductPhoto
{
private string addrField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string addr
{
get
{
return this.addrField;
}
set
{
this.addrField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsProductParameter
{
private string nameField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
}
}
rule1.xml
This rule has proper type testSlimWebRule.productsProduct. It gets evaluated against each element in the auto-generated array of testSlimWebRule.productsProduct.
<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
<rule id="09973a56-3d6a-4616-ae1c-40d0d17e95b9" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="testSlimWebRule.productsProduct, testSlimWebRule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" eval="true">
<definition>
<condition type="equal">
<property name="id" />
<value type="numeric">1</value>
</condition>
</definition>
</rule>
</codeeffects>
rule2.xml
This rule is the way you would have. It is applied to objects of type System.Xml.Linq.XElement. As such it can only operate on properties and methods of that type, i.e. you don't get your custom fields id, addr, name, etc.
<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
<rule id="e38da351-1190-47fb-b99b-d06787c9a459" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" eval="true">
<definition>
<condition type="equal">
<property name="FirstAttribute.Value" />
<value>1</value>
</condition>
</definition>
</rule>
</codeeffects>
rule3.xml
This rule does not have any type. Instead it receives whatever type it is evaluated against. In the example it gets anonymous type 'a, so it can operate on properties ID, Name, and Addr.
<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
<rule id="7d72463f-5ae2-4617-a2bf-fd605fcb4f54" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="" eval="true">
<definition>
<condition type="startsWith">
<property name="Addr" />
<value>2</value>
</condition>
</definition>
</rule>
</codeeffects>
I am using GlassFish server in Eclipse and am trying to intergerate the hibernate-release-5.1.0.Final into the JSF project. I have tried several steps but without seccuss.
I have Placed the Hibernate Jars inside the GlassFisch directrory glassfish4\bin and restarted the server.
I placed them inside the following foloder glassfish4\glassfish\bin and restarted the GlassFisch server.
I placed the Hibernate jars inside the WEB-INF/lib
I added this part .addResource("/resources/person.hbm.xml") to the CreatePersonDemo class.
I replaced the jboss-logging.jar inside the glassfish4\glassfish\modules directory with jboss-logging-3.3.0.Final.jar
CreatePersonDemo
package com.backing;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.model.Person;
public class CreatePersonDemo {
public static void main(String[] args) {
// create session factory.
// SessionFactory factory = new Configuration()
// .configure("/resources/hibernate.cfg.xml")
// .addAnnotatedClass(Person.class)
// .buildSessionFactory();
SessionFactory factory = new Configuration().configure("/resources/hibernate.cfg.xml")
.addResource("/resources/person.hbm.xml")
.addAnnotatedClass(Person.class)
.buildSessionFactory();
// create a session.
Session session = factory.getCurrentSession();
System.out.println("CreateStudentDemo");
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/GMapsYahooMeshup</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<mapping resource="resources/person.hbm.xml" />
<!-- <mapping class ="com.Model.Person" /> -->
</session-factory>
</hibernate-configuration>
person.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Person" table="person">
<meta attribute="class-description">
This class contains the person detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="full_name" column="full_name" type="string" />
<property name="email " column="email " type="string" />
<property name="location" column="location" type="string" />
<property name="pwd" column="pwd" type="string" />
</class>
</hibernate-mapping>
Person.Java
package com.model;
public class Person {
private int id;
private String full_name;
private String email;
private String location;
private String pwd;
public Person(int id, String full_name, String email, String location, String pwd) {
super();
this.id = id;
this.full_name = full_name;
this.email = email;
this.location = location;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFull_name() {
return full_name;
}
public void setFull_name(String full_name) {
this.full_name = full_name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
Error
org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=root, password=****}
Jul 17, 2016 10:24:52 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Exception in thread "main" java.lang.NoSuchMethodError: org.hibernate.internal.CoreMessageLogger.debugf(Ljava/lang/String;I)V
at org.hibernate.engine.jdbc.connections.internal.PooledConnections.<init>(PooledConnections.java:34)
at org.hibernate.engine.jdbc.connections.internal.PooledConnections.<init>(PooledConnections.java:19)
at org.hibernate.engine.jdbc.connections.internal.PooledConnections$Builder.build(PooledConnections.java:138)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.buildPool(DriverManagerConnectionProviderImpl.java:110)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:74)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:87)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:692)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at com.backing.CreatePersonDemo.main(CreatePersonDemo.java:22)
Project structure
My batch job will generate 2 text files with string format per line. I created a reader
<bean id="myMultiResourceReader"
class=" org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="file:D:/MY/sample/*.txt" />
</bean>
<bean id="myFinalWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
scope="step">
<property name="resource" value="${test.file3}" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="footerCallback" ref="myFinalCustomItemWriter" />
<property name="headerCallback" ref="myFinalCustomItemWriter" />
</bean>
<bean id="myFinalCustomItemWriter" class="my.process.MyWriter"
scope="step">
<property name="delegate" ref="myFinalWriter" />
<property name="stepContext" value="#{stepExecution.stepName}" />
</bean>
I was getting this error:
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.FlatFileItemWriter' for property 'delegate'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found
Basically I just want to combine two plain file, and append the total count at footer. Then delete away the both input file. Can help?
MyWriter.java
public class MyWriter implements ItemWriter<String>, FlatFileFooterCallback, FlatFileHeaderCallback, ItemStream{
private static Logger log = Logger.getLogger(MyWriter.class);
private FlatFileItemWriter<String> delegate;
private int recordCount = 0;
private String stepContext;
public void writeFooter(Writer writer) throws IOException {
writer.write("#" + recordCount);
}
public void writeHeader(Writer writer) throws IOException {
writer.write("#" + StringUtil.getSysDate());
}
public void setDelegate(FlatFileItemWriter<String> delegate) {
this.delegate = delegate;
}
public void write(List<? extends String> list) throws Exception {
int chunkRecord = 0;
for (String item : list) {
chunkRecord++;
}
delegate.write(list);
recordCount += chunkRecord;
}
public void close() throws ItemStreamException {
this.delegate.close();
}
public void open(ExecutionContext arg0) throws ItemStreamException {
this.delegate.open(arg0);
}
public void update(ExecutionContext arg0) throws ItemStreamException {
this.delegate.update(arg0);
}
public void setStepContext(String stepContext) {
this.stepContext = stepContext;
}
}
As Luca Basso Ricci already pointed out, the problem is your delegate definition in MyWriter. Since Spring creates proxies for it beans, it will not recognize your FlatFileItemReader as an actual instance of FlatFileItemWriter and, therefore, the setDelegate(FlatFileItemWriter delegate) will fail.
Use an ItemStreamWriter in MyWriter. As you see in the exception message, the created proxy does provide this interface. Hence, it can be inserted
This will solve the delegation to write, open, close, and update method. In order to write the header and footer, you need to implement a HeaderCallback and FooterCallback and set it directly in the definition of your FlatFileItemWriter.
Implementing the HeaderCallback is not a problem since you only set the systemdate.
As FooterCallback, make your own Bean. Use it in the FlatFileItemWriter to write the footer. Add an "increaseCount" method to it and use it in your MyWriter Bean to increase the written count.
public void write(List<? extends String> list) throws Exception {
myFooterCallback.increaseCount(list.size());
delegate.write(list);
}
Another possible option would be to directly extend MyWriter from FlatFileItemWriter:
public class MyWriter extends FlatFileItemWriter<String> implements FlatFileFooterCallback, FlatFileHeaderCallback{
private static Logger log = Logger.getLogger(MyWriter.class);
private int recordCount = 0;
private String stepContext;
public void writeFooter(Writer writer) throws IOException {
writer.write("#" + recordCount);
}
public void writeHeader(Writer writer) throws IOException {
writer.write("#" + StringUtil.getSysDate());
}
public void afterPropertiesSet() {
setFooterCallback(this);
setHeaderCallback(this);
super.afterPropertiesSet();
}
public void write(List<? extends String> list) throws Exception {
super.write(list);
recordCount += list.size();
}
}
Configuration in your XML would look like this:
<bean id="myFinalCustomItemWriter" class="my.process.MyWriter" scope="step">
<property name="resource" value="${test.file3}" />
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="stepContext" value="#{stepExecution.stepName}" />
</bean>
Ok here iam back to find a solution.
Iam trying Spring RestTemplate postForEntity method to send a Collection of instances. When attempting spring gives an error org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [com.abc.base.domai
n.dto.gift.GiftItemList Appriciate, if someone can tells me how to send a an ArrayList with spring resttemplate POST method.
RestTemplate bean:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="httpClientFactory"/>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean id="jsonViewResolver" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name="objectMapper">
<ref bean="JacksonObjectMapper" />
</property>
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg value="application" />
<constructor-arg value="json" />
<constructor-arg value="#{T(java.nio.charset.Charset).forName('UTF-8')}"/>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
<bean id="JacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<constructor-arg ref="httpClientParams"/>
</bean>
<bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">
<property name="connectionManagerClass" value="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
</bean>
<bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
</bean>
Instance that iam trying to POST,
public class GiftItem implements Entity, Serializable {
private static final long serialVersionUID = 1L;
private String redeemLocation;
private String itemName;
private String itemDescription;
private String merchantName;
private Integer quantity;
private Integer imageId;
public GiftItem() {
super();
}
//with getters and setters
}
GiftItem instance wraaper class
public class GiftItemList implements Serializable {
private static final long serialVersionUID = -8202204714984099030L;
public GiftItemList() {
}
private List<GiftItem> giftItemList;
public List<GiftItem> getGiftItemList() {
return giftItemList;
}
public void setGiftItemList(List<GiftItem> giftItemList) {
this.giftItemList = giftItemList;
}
}
this is how i use it,
public BaseResponse sendGiftEmail(final String token, final User sender,final String message, final GiftItemList giftItemList) {
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("token", token);
map.add("sender", sender);
map.add("message", message);
map.add("giftItemList", giftItemList);
return getRestTemplate().postForEntity(
"http://localhost:8080/notification/api/notification/send_gift_email",
map, BaseResponse.class).getBody();
}
and the error i am getting,
org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [com.abc.base.domain.dto.gift.GiftItemList]
at org.springframework.http.converter.FormHttpMessageConverter.write Part(FormHttpMessageConverter.java:310)
at org.springframework.http.converter.FormHttpMessageConverter.write Parts(FormHttpMessageConverter.java:270)
at org.springframework.http.converter.FormHttpMessageConverter.write Multipart(FormHttpMessageConverter.java:260)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:200)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:302)
at com.tapgift.gift.client.impl.GiftClientImpl.sendGiftNotifications(GiftClientImpl.java:101)
pom:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.2</version>
</dependency>
almost forgot receiver controller,
#RequestMapping(value = "/notification/send_gift_email", method = RequestMethod.POST)
public #ResponseBody BaseResponse sendGiftEmail(#RequestParam("token") String token, #RequestParam("sender")final User sender, #RequestParam("message")final String message,#RequestParam("giftItemList") GiftItemList giftItemList) {
}
You have to add MappingJacksonHttpMessageConveter to your messageCoverter :
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJacksonHttpMessageConverter());
restTemplate = new RestTemplate();
restTemplate.setMessageConverters(messageConverters);
You also need to add the dependency for :
jackson-core-asl-x.x.x.jar & jaackson.mapper.asl-x.x.x.jar
Another thing, you have to make sure that your class have the same attribute as your JSON properties. For example :
{"data":{"ticket":"TICKET_870299cf98e227abdbd5f9b7064390c5723a0c6a"}}
To fill your class properties, they have to be like this :
person.java
public class person {
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
data.java
public class Data {
private String ticket;
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
}
Finaly in your application your add :
person entity = restTemplate.postForObject(url, requestEntity,
person.class);
requestEntity is a String that contains your request body (JSON in my case).
Hope that helped !