I have this Java class where I am writing the code for applying the overrides. I want to know if using ENUM is appropriate or if I need to use the switch case, how can I use it? Also, I have the for loop that I need to use as a common block of code for each override type. Apart from that, I do have few separate fields that I need to code for each override type.
public class EWFMService
{
private WorkbrainSystemAccessService wsa = new WorkbrainSystemAccessService();
private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(EWFMService.class);
private final static String ovrCalcGrp = "ovrCalcGrp";
private DBConnection conn = null;
private int empId;
private Date ovrDate;
private String ovrTime;
private String ovrAction;
public List<EWFMServiceData> getProcessEWFMOverrides(String userName, String password, List<EWFMServiceInputData> inputData)
throws WSApplicationException{
logger.debug("EWFM Service");
wsa.logOn(userName, password);
List<EWFMServiceData> returnList = new ArrayList<EWFMServiceData> ();
logger.debug("userName = " + userName);
DBConnection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = new DBConnection(ConnectionManager.getConnection());
for (int i = 0; i < inputData.size(); i++)
{
Here I want to retrieve the emp_id from the database, store the value in a variable and be able to use the variable in the rest of my program. How do I do it? To retrieve the emp_id, I am using the following query.
conn = new DBConnection(ConnectionManager.getConnection());
String sql = "SELECT EMP_ID FROM EMPLOYEE_HISTORY"
+ " WHERE EMP_VAL2 = **This is where I want to use the variable in which the values of emp_id will be stored. There can be more than 100 emp_ids**"
+ " AND SYSDATE BETWEEN EMPHIST_START_DATE AND EMPHIST_END_DATE";
EWFMServiceInputData inData = (EWFMServiceInputData) inputData.get(i);
OverrideType ot = OverrideType.getOverrideType(inData.getRecordType());
logger.debug("override type = " + ot.toString());
logger.debug("inputData ["+i+"] = " + inData.toString());
OverrideAccess oa = new OverrideAccess(conn);
OverrideData ovr = new OverrideData();
ovr.setOvrUdf4(inData.getReferenceId().toString());
if (ovrAction.equals("APPLY")) {
ovr.setOvrStatus(OverrideData.PENDING);
Here I want to determine the Action. If it is Apply, then I need to find out the recordType. So basically branch it out for each recordType using if else statements or enum as I believe switch doesn't support Java 1.5 which is what I am using. Then for each recordType, I branch out and write the appropriate code corresponding to that recordType. If Action is CANCEL, then I just write the following code.
} else if (ovrAction.equals("CANCEL")) {
String sql = "SELECT * FROM OVERRIDE"
+ " WHERE OVR_UDF4 = ?"
+ " AND OVRTYP_ID = ?";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()); {
ovr.assignByName(rs);
ovr.setUpdated(false);
ovr.setRetrieved(true);
ovr.setOvrStatus(OverrideData.CANCEL);
oa.save(ovr);
}
}
ovr.setEmpId(empId);
String strOvrDate = inData.getOvrStartDate();
ovr.setOvrStartDate(DateHelper.parseDate(strOvrDate, "MM/dd/yyyy"));
if (ovrStartTime != null) {
ovr.setOvrStartTime(ovrTime);
}
Object ovrEndDate;
if (ovrEndDate != null) {
ovr.setOvrEndDate(ovrDate);
}
Object ovrEndTime;
if (ovrEndTime!= null) {
ovr.setOvrEndTime(ovrTime);
}
ovr.setOvrComment(inData.getOvrComments());
ovr.setWbuName(inData.getWbuName());
ovr.setWbuNameActual(inData.getWbuNameActual());
ovr.setOvrNewValue("VAC");
ovr.setOvrCreateDate(new Date());
ovr.setOvrtypId(103);
oa.insert(ovr);
RuleEngine.runCalcGroup(conn,
empId,
ovrDate,
ovrDate);
//COMMON BLOCK ENDS HERE
EWFMServiceData outData = new EWFMServiceData();
outData.setReferenceId(inData.getReferenceId());
String [] status = {"SUCCESS", "ERROR", "LOCKED", "EXCEPTION"};
Random ran = new Random();
String gen = status[ran.nextInt(status.length)];
logger.debug("Status is" + status );
outData.setStatus(gen);
if (gen.equals("SUCCESS")){
outData.setErrorDetails("");
} else if (gen.equals("ERROR")) {
outData.setErrorDetails("Usage of time code VAC is not allowed; balance is insufficient." + " error");
} else if (gen.equals("LOCKED")) {
outData.setErrorDetails("Timesheet cannot be edited because it is locked for payroll close." + "locked");
} else if (gen.equals("EXCEPTION")) {
outData.setErrorDetails("{ML}QR_INCORRECT_CONDITION_PARAMETER{/ML}Error in condition AWA Is Self Override Condition: java.lang.NullPointerException{ARGS}AWA Is Self Override Conditionjava.lang.NullPointerException{/ARGS" + "exception");
}
returnList.add(outData);
}
}catch (Exception e){
logger.error("Error occured",e);
throw new WSApplicationException("Error retrieved",e);
}finally{
SQLUtil.cleanUp(conn, ps, rs);
}
wsa.logOff();
logger.debug("inputData+ ");
return returnList;
}
// I need to know if writing enum is okay or can I just write a switch case above in the for loop and branch each override type and declare their individual variables there? What's the best way? Can someone help me with the code?
public enum OverrideType {
WORKDETAIL,
WORKPREMIUM,
EMPLOYEESCHEDULE,
EMPLOYEE;
public static OverrideType getOverrideType(String recordType) {
if(recordType == null) {
throw new IllegalArgumentException("Record Type cannot be null");
}
if(recordType.equals("Work Detail")) {
return WORKDETAIL;
} else if (recordType.equals("Work Premium")) {
return WORKPREMIUM;
} else if (recordType.equals("Schedule")) {
return EMPLOYEESCHEDULE;
} else if (recordType.equals("Shift Pattern")) {
return EMPLOYEE;
} else {
throw new IllegalArgumentException("Record Type cannot be" + recordType);
}
}
}
}
THE OTHER FIELDS I NEED TO INCLUDE ARE AS FOLLOWS:
FOR WORKDETAIL, I NEED TO USE TIMECODE OF FORMAT THAT IS SENT BY THE CLIENT.
FOR WORK PREMIUM, I NEED TO USE TIMECODE OF FORMAT THAT IS SENT BY THE CLIENT AND ANOTHER FIELD IS MINUTES THAT GIVES THE NUMBER OF MINUTES WHICH IS ALSO SENT BY THE CLIENT.
Generally, using enums is appropriate, especially if you have a defined set of possible types.
You can also add behavior to the enums, which could make your enum a little bit more sophisticated:
public enum OverrideType {
WORKDETAIL("Work Detail"),
WORKPREMIUM("Work Premium"),
EMPLOYEESCHEDULE("Schedule"),
EMPLOYEE("Shift Pattern");
private String identifier;
private OverrideType(String identifier){
this.identifier = identifier;
}
public static OverrideType getOverrideType(String recordType) {
if(recordType == null) {
throw new IllegalArgumentException("Record Type cannot be null");
}
for (OverrideType ot : OverrideType.values()) {
if (recordType.equals(ot.identifier)) {
return ot;
}
}
return null;
}
}
The following example shows how to use an interface in enums or an abstract method definition:
public enum OverrideType implements OverrideTypeIF {
WORKDETAIL("Work Detail") {
public int getKey() {
return 0;
}
},
WORKPREMIUM("Work Premium") {
public int getKey() {
return 0;
}
},
EMPLOYEESCHEDULE("Schedule") {
public int getKey() {
return 0;
}
},
EMPLOYEE("Shift Pattern") {
public int getKey() {
return 0;
}
public void myInterfaceMethod() {
// do type specific behavior
}
};
private String identifier;
private OverrideType(String identifier){
this.identifier = identifier;
}
public abstract int getKey();
public void myInterfaceMethod() {
// do default behavior
}
public static OverrideType getOverrideType(String recordType) {
if(recordType == null) {
throw new IllegalArgumentException("Record Type cannot be null");
}
for (OverrideType ot : OverrideType.values()) {
if (recordType.equals(ot.identifier)) {
return ot;
}
}
return null;
}
}
public interface OverrideTypeIF {
void myInterfaceMethod();
}
Related
Can someone share some sample codes on how to set the value of a non-editable Combobox? It is similar to this, but when I tried to insert it in my code. It returns a null value
Code
ObservableList<City> data = FXCollections.observableArrayList();
data = AddressGetWay.getCityByProvince("Batanes")
cmbCity.setItems(data); // set the items from the database
cmbCity.setConverter(new StringConverter<City>() {
#Override
public String toString(City object) {
return object.getCityName();
}
#Override
public City fromString(String string) {
return cmbCity.getItems().stream().filter(ap
-> ap.getCityName().equals(string)).findFirst().orElse(null);
}
});
cmbCity.valueProperty().addListener(
(ObservableValue<? extends City> observable, City oldValue, City newVal) -> {
if (newVal != null) {
//
}
}
);
// TODO: get the data stored in the database (Column City)
// and set the value of the ComboBox.
Predicate<City> predicate = city -> city.getCityName() == "Itbayat"; // Let's assume that the data stored in the database is "Itbayat"
Optional<City> opt = data.stream().filter(predicate).findAny();
cmbCity.getSelectionModel().select(opt.orElse(null)); // the ComboBox value should be "Itbayat".
I'm using a Singleton Class (correct me if I'm wrong) to retrieve the data from the database
public class AddressGetWay {
static Connection con; //connect to the database
static PreparedStatement pst = null;
static ResultSet rs = null;
public static ObservableList<City> getCityByProvince(String prov) {
ObservableList<City> listData = FXCollections.observableArrayList();
String sql = "SELECT pk_cit_id, cit_nm, zip_code FROM city_mun WHERE prov_code = (SELECT prov_code FROM provinces WHERE prov_nm = ?)";
try {
pst = con.prepareStatement(sql);
pst.setString(1, prov);
rs = pst.executeQuery();
while (rs.next()) {
listData.add(new City(
rs.getInt(1),
rs.getString(2),
rs.getInt(3)
));
}
} catch (SQLException ex) {
Logger.getLogger(AddressGetWay.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
pst.close();
rs.close();
} catch (SQLException ex) {
Logger.getLogger(AddressGetWay.class.getName()).log(Level.SEVERE, null, ex);
}
}
return listData;
}
}
This should be my desired Output
But I got this output using the above code
As for my naming conventions. I tried to do this if there's something I need to correct, feel free to pinpoint.
It seems that you are having issue on this code block,
ObservableList<City> data = AddressGetWay.getCityByProvince("Batanes");
//....
Predicate<City> predicate = city -> city.getCityName() == "Itbayat";
Optional<City> opt = data.stream().filter(predicate).findAny();
cmbCity.getSelectionModel().select(opt.orElse(null));
I suspect some loop-holes that is overcoming the null-value.
As you retrieving data through province Batanes i.e. ObservableList<City> data = AddressGetWay.getCityByProvince("Batanes"), maybe it's not retrieving any data.
Your predicate is comparing cityName Itbayat, which may not be getting matched with the retrieved data.
Please check the database value for the city table as to compare those data as well
AddressGateWay
public class AddressGateWay {
private static Connection connection;
private static PreparedStatement statement = null;
private static ResultSet result = null;
static {
connection = loadConnection();
}
public static ObservableList<City> getCityByProvince(String prov) {
ObservableList<City> listData = FXCollections.observableArrayList();
String sql = "SELECT pk_cit_id, cit_nm, zip_code FROM city_mun WHERE prov_code = (SELECT prov_code FROM provinces WHERE prov_nm = ?)";
try {
statement = connection.prepareStatement(sql);
statement.setString(1, prov);
result = statement.executeQuery();
while (result.next()) {
listData.add(new City(
result.getInt(1),
result.getString(2)
));
}
} catch (SQLException ex) {
Logger.getLogger(AddressGateWay.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
statement.close();
result.close();
} catch (SQLException ex) {
Logger.getLogger(AddressGateWay.class.getName()).log(Level.SEVERE, null, ex);
}
}
return listData;
}
// for editing
public static ObservableList<Address> selectedItem(int item) {
ObservableList<Address> listData = FXCollections.observableArrayList();
String sql = "SELECT prov_nm, city_nm FROM emp_address WHERE pk_address_id = ?";
try {
statement = connection.prepareStatement(sql);
statement.setString(1, item);
result = statement.executeQuery();
if (result.next()) {
listData.add(new Address(
result.getString(1),
result.getString(2)
));
}
} catch (SQLException ex) {
Logger.getLogger(AddressGateWay.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
statement.close();
result.close();
} catch (SQLException ex) {
Logger.getLogger(AddressGateWay.class.getName()).log(Level.SEVERE, null, ex);
}
}
return listData;
}
}
City
public class City {
private int id;
private String cityName;
public City(int id, String cityName) {
this.id = id;
this.cityName = cityName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
}
Controller Logic Code
ObservableList<City> cities = AddressGateWay.getCityByProvince(provinceComboBox.getValue()); // assume the value is "Batanes"
cityComboBox.setItems(cities);
cityComboBox.setConverter(new StringConverter<City>() {
#Override
public String toString(City object) {
return object.getCityName();
}
#Override
public City fromString(String string) {
return cityComboBox.getItems().stream().filter(ap
-> ap.getCityName().equals(string)).findFirst().orElse(null);
}
});
cityComboBox.valueProperty().addListener(
(ObservableValue<? extends City> observable, City oldValue, City newVal) -> {
if (newVal != null) {
//
}
}
);
City city = cities
.stream()
.filter(c -> c.getCityName() == "Itbayat")
.findAny()
.orElse(null);
cityComboBox.getSelectionModel().select(city);
// summing up the below updates and your codes,
// I have set the value of cityComboBox by using . . .
Address ads = new Address();
ads = AddressGetWay.selectedItem(item); // the item to be edit
// assume the value from the database is "Itbayat"
Predicate<City> predicate = city -> city.getCityName() == ads.getCity().getCityName();
Optional<City> opt = cities.stream().filter(predicate).findAny();
cityComboBox.getSelectionModel().select(opt.orElse(null));
// Thank you, it finally work :)
Some key points based on the updated code
Refactoring code based on unnecessary code
Implementing basic Java naming Conventions
Missing connection initialization (need to load based on your database)
Inined code (for Predicate, and Optional)
EDIT
Province
public class Province {
private String provinceCode;
private String provinceName;
//Constructors
//Getters and Setters
}
Address
public class Address {
private City city;
private Province province;
//Constructors
//Getters and Setters
}
Getting error preverifying class java/langnoclassdeffounderror : java/lang/comparable for java me platform.
I have migrated my J2SE code to J2ME code. I am aware that some functions J2SE functions don't work on J2ME platform. Therefore, i have already crosschecked for the Comparable class. It is included in Java ME libraries.
Now, i am unable to resolve the errors. Please help me out here.
Please refer the code below:
import java.io.Serializable;
import aiproject.CompareToBuilder;
import aiproject.EqualsBuilder;
import aiproject.HashCodeBuilder;
import aiproject.ToStringBuilder;
public class WordProbability implements Comparable, Serializable {
private static final int UNDEFINED = -1;
private String word = "";
private String category = ICategorisedCategorizer.DEFAULT_CATEGORY;
private long matchingCount = UNDEFINED;
private long nonMatchingCount = UNDEFINED;
private double probability = ICategorizer.NEUTRAL_PROBABILITY;
public WordProbability() {
setMatchingCount(0);
setNonMatchingCount(0);
}
public WordProbability(String w) {
setWord(w);
setMatchingCount(0);
setNonMatchingCount(0);
}
public WordProbability(String c, String w) {
setCategory(c);
setWord(w);
setMatchingCount(0);
setNonMatchingCount(0);
}
public WordProbability(String w, double probability) {
setWord(w);
setProbability(probability);
}
public WordProbability(String w, long matchingCount, long nonMatchingCount) {
setWord(w);
setMatchingCount(matchingCount);
setNonMatchingCount(nonMatchingCount);
}
public void setWord(String w) {
this.word = w;
}
public void setCategory(String category) {
this.category = category;
}
public void setProbability(double probability) {
this.probability = probability;
this.matchingCount = UNDEFINED;
this.nonMatchingCount = UNDEFINED;
}
public void setMatchingCount(long matchingCount) {
if (matchingCount < 0) {
throw new IllegalArgumentException("matchingCount must be greater than 0");
}
this.matchingCount = matchingCount;
calculateProbability();
}
public void setNonMatchingCount(long nonMatchingCount) {
if (nonMatchingCount < 0) {
throw new IllegalArgumentException("nonMatchingCount must be greater than 0");
}
this.nonMatchingCount = nonMatchingCount;
calculateProbability();
}
public void registerMatch() {
if (matchingCount == Long.MAX_VALUE) {
throw new UnsupportedOperationException("Long.MAX_VALUE reached, can't register more matches");
}
matchingCount++;
calculateProbability();
}
public void registerNonMatch() {
if (nonMatchingCount == Long.MAX_VALUE) {
throw new UnsupportedOperationException("Long.MAX_VALUE reached, can't register more matches");
}
nonMatchingCount++;
calculateProbability();
}
private void calculateProbability() {
String method = "calculateProbability() ";
double result = ICategorizer.NEUTRAL_PROBABILITY;
if (matchingCount == 0) {
if (nonMatchingCount == 0) {
result = ICategorizer.NEUTRAL_PROBABILITY;
} else {
result = ICategorizer.LOWER_BOUND;
}
} else {
result = BayesianCategorizer.normaliseSignificance((double) matchingCount / (double) (matchingCount + nonMatchingCount));
}
probability = result;
}
/**
* output
*/
public double getProbability() {
return probability;
}
public long getMatchingCount() {
if (matchingCount == UNDEFINED) {
throw new UnsupportedOperationException("MatchingCount has not been defined");
}
return matchingCount;
}
public long getNonMatchingCount() {
if (nonMatchingCount == UNDEFINED) {
throw new UnsupportedOperationException("nonMatchingCount has not been defined");
}
return nonMatchingCount;
}
public String getWord() {
return word;
}
public String getCategory() {
return category;
}
public boolean equals(Object o) {
if (!(o instanceof WordProbability)) {
return false;
}
WordProbability rhs = (WordProbability) o;
return new EqualsBuilder().append(getWord(), rhs.getWord()).append(getCategory(), rhs.getCategory()).isEquals();
}
public int compareTo(java.lang.Object o) {
if (!(o instanceof WordProbability)) {
throw new ClassCastException(o.getClass() + " is not a " + this.getClass());
}
WordProbability rhs = (WordProbability) o;
return new CompareToBuilder().append(this.getCategory(), rhs.getCategory()).append(this.getWord(), rhs.getWord()).toComparison();
}
public String toString() {
return new ToStringBuilder(this).append("word", word).append("category", category).append("probability", probability).append("matchingCount", matchingCount).append("nonMatchingCount", nonMatchingCount).toString();
}
public int hashCode() {
return new HashCodeBuilder(17, 37).append(word).append(category).toHashCode();
}
}
I don't see a Comparable in the javadocs of JavaME.
So I think it is not there.
Where did you found it?
Maybe some Lib or JSR has included it. Than you need to include this in the project settings.
If you just need the interface, you can define it yourself.
In Python I can consume a web service so easily:
from suds.client import Client
client = Client('http://www.example.org/MyService/wsdl/myservice.wsdl') #create client
result = client.service.myWSMethod("Bubi", 15) #invoke method
print result #print the result returned by the WS method
I'd like to reach such a simple usage with Java.
With Axis or CXF you have to create a web service client, i.e. a package which reproduces all web service methods so that we can invoke them as if they where normal methods. Let's call it proxy classes; usually they are generated by wsdl2java tool.
Useful and user-friendly. But any time I add/modify a web service method and I want to use it in a client program I need to regenerate proxy classes.
So I found CXF DynamicClientFactory, this technique avoids the use of proxy classes:
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
//...
//create client
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://www.example.org/MyService/wsdl/myservice.wsdl");
//invoke method
Object[] res = client.invoke("myWSMethod", "Bubi");
//print the result
System.out.println("Response:\n" + res[0]);
But unfortunately it creates and compiles proxy classes runtime, hence requires JDK on the production machine. I have to avoid this, or at least I can't rely on it.
My question:
Is there another way to dinamically invoke any method of a web service in Java, without having a JDK at runtime and without generating "static" proxy classes? Maybe with a different library? Thanks!
I know this is a really old question but if you are still interested you could use soap-ws github project: https://github.com/reficio/soap-ws
Here you have a sample usage really simple:
Wsdl wsdl = Wsdl.parse("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
SoapBuilder builder = wsdl.binding()
.localPart("CurrencyConvertorSoap")
.find();
SoapOperation operation = builder.operation()
.soapAction("http://www.webserviceX.NET/ConversionRate")
.find();
Request request = builder.buildInputMessage(operation)
SoapClient client = SoapClient.builder()
.endpointUrl("http://www.webservicex.net/CurrencyConvertor.asmx")
.build();
String response = client.post(request);
As you can see it is really simple.
With CXF 3.x this could be possible with StaxDataBinding. Follow below steps to get the basics. Of course, this could be enhanced to your needs.
Create StaxDataBinding something like below. Note below code can be enhanced to your sophistication.
class StaxDataBinding extends AbstractInterceptorProvidingDataBinding {
private XMLStreamDataReader xsrReader;
private XMLStreamDataWriter xswWriter;
public StaxDataBinding() {
super();
this.xsrReader = new XMLStreamDataReader();
this.xswWriter = new XMLStreamDataWriter();
inInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inFaultInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
inFaultInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
}
static class RemoveStaxInEndingInterceptor
extends AbstractPhaseInterceptor<Message> {
static final RemoveStaxInEndingInterceptor INSTANCE = new RemoveStaxInEndingInterceptor();
public RemoveStaxInEndingInterceptor() {
super(Phase.PRE_INVOKE);
addBefore(StaxInEndingInterceptor.class.getName());
}
public void handleMessage(Message message) throws Fault {
message.getInterceptorChain().remove(StaxInEndingInterceptor.INSTANCE);
}
}
public void initialize(Service service) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
SchemaCollection schemaCollection = serviceInfo.getXmlSchemaCollection();
if (schemaCollection.getXmlSchemas().length > 1) {
// Schemas are already populated.
continue;
}
new ServiceModelVisitor(serviceInfo) {
public void begin(MessagePartInfo part) {
if (part.getTypeQName() != null
|| part.getElementQName() != null) {
return;
}
part.setTypeQName(Constants.XSD_ANYTYPE);
}
}.walk();
}
}
#SuppressWarnings("unchecked")
public <T> DataReader<T> createReader(Class<T> cls) {
if (cls == XMLStreamReader.class) {
return (DataReader<T>) xsrReader;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedReaderFormats() {
return new Class[] { XMLStreamReader.class };
}
#SuppressWarnings("unchecked")
public <T> DataWriter<T> createWriter(Class<T> cls) {
if (cls == XMLStreamWriter.class) {
return (DataWriter<T>) xswWriter;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedWriterFormats() {
return new Class[] { XMLStreamWriter.class, Node.class };
}
public static class XMLStreamDataReader implements DataReader<XMLStreamReader> {
public Object read(MessagePartInfo part, XMLStreamReader input) {
return read(null, input, part.getTypeClass());
}
public Object read(QName name, XMLStreamReader input, Class<?> type) {
return input;
}
public Object read(XMLStreamReader reader) {
return reader;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String prop, Object value) {
}
}
public static class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
private static final Logger LOG = LogUtils
.getL7dLogger(XMLStreamDataWriter.class);
public void write(Object obj, MessagePartInfo part, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
// WRITE YOUR LOGIC HOW you WANT TO HANDLE THE INPUT DATA
//BELOW CODE JUST CALLS toString() METHOD
if (part.isElement()) {
QName element = part.getElementQName();
writer.writeStartElement(element.getNamespaceURI(),
element.getLocalPart());
if (obj != null) {
writer.writeCharacters(obj.toString());
}
writer.writeEndElement();
}
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
public void write(Object obj, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
throw new UnsupportedOperationException("Data types of "
+ obj.getClass() + " are not supported.");
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
private boolean doWrite(Object obj, XMLStreamWriter writer)
throws XMLStreamException {
if (obj instanceof XMLStreamReader) {
XMLStreamReader xmlStreamReader = (XMLStreamReader) obj;
StaxUtils.copy(xmlStreamReader, writer);
xmlStreamReader.close();
return true;
}
else if (obj instanceof XMLStreamWriterCallback) {
((XMLStreamWriterCallback) obj).write(writer);
return true;
}
return false;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String key, Object value) {
}
}
}
Prepare your input to match the expected input, something like below
private Object[] prepareInput(BindingOperationInfo operInfo, String[] paramNames,
String[] paramValues) {
List<Object> inputs = new ArrayList<Object>();
List<MessagePartInfo> parts = operInfo.getInput().getMessageParts();
if (parts != null && parts.size() > 0) {
for (MessagePartInfo partInfo : parts) {
QName element = partInfo.getElementQName();
String localPart = element.getLocalPart();
// whatever your input data you need to match data value for given element
// below code assumes names are paramNames variable and value in paramValues
for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(localPart)) {
inputs.add(findParamValue(paramNames, paramValues, localPart));
}
}
}
}
return inputs.toArray();
}
Now set the proper data binding and pass the data
Bus bus = CXFBusFactory.getThreadDefaultBus();
WSDLServiceFactory sf = new WSDLServiceFactory(bus, wsdl);
sf.setAllowElementRefs(false);
Service svc = sf.create();
Client client = new ClientImpl(bus, svc, null,
SimpleEndpointImplFactory.getSingleton());
StaxDataBinding databinding = new StaxDataBinding();
svc.setDataBinding(databinding);
bus.getFeatures().add(new StaxDataBindingFeature());
BindingOperationInfo operInfo = ...//find the operation you need (see below)
Object[] inputs = prepareInput(operInfo, paramNames, paramValues);
client.invoke("operationname", inputs);
If needed you can match operation name something like below
private BindingOperationInfo findBindingOperation(Service service,
String operationName) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
Collection<BindingInfo> bindingInfos = serviceInfo.getBindings();
for (BindingInfo bindingInfo : bindingInfos) {
Collection<BindingOperationInfo> operInfos = bindingInfo.getOperations();
for (BindingOperationInfo operInfo : operInfos) {
if (operInfo.getName().getLocalPart().equals(operationName)) {
if (operInfo.isUnwrappedCapable()) {
return operInfo.getUnwrappedOperation();
}
return operInfo;
}
}
}
}
return null;
}
i'am trying to modify my objects to make hierarchical collection model. I need help. My objects are Good and GoodCategory:
public class Good
{
int _ID;
int _GoodCategory;
string _GoodtName;
public int ID
{
get { return _ID; }
}
public int GoodCategory
{
get { return _GoodCategory; }
set
{
_GoodCategory = value;
}
}
public string GoodName
{
get { return _GoodName; }
set
{
_GoodName = value;
}
}
public Good(IDataRecord record)
{
_ID = (int)record["ID"];
_GoodtCategory = (int)record["GoodCategory"];
}
}
public class GoodCategory
{
int _ID;
string _CategoryName;
public int ID
{
get { return _ID; }
}
public string CategoryName
{
get { return _CategoryName; }
set
{
_CategoryName = value;
}
}
public GoodCategory(IDataRecord record)
{
_ID = (int)record["ID"];
_CategoryName = (string)record["CategoryName"];
}
}
And I have two Collections of these objects:
public class GoodsList : ObservableCollection<Good>
{
public GoodsList()
{
string goodQuery = #"SELECT `ID`, `ProductCategory`, `ProductName`, `ProductFullName` FROM `products`;";
using (MySqlConnection conn = ConnectToDatabase.OpenDatabase())
{
if (conn != null)
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = productQuery;
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Add(new Good(rdr));
}
}
}
}
}
public class GoodCategoryList : ObservableCollection<GoodCategory>
{
public GoodCategoryList ()
{
string goodQuery = #"SELECT `ID`, `CategoryName` FROM `product_categoryes`;";
using (MySqlConnection conn = ConnectToDatabase.OpenDatabase())
{
if (conn != null)
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = productQuery;
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Add(new GoodCategory(rdr));
}
}
}
}
}
So I have two collections which takes data from the database. But I want to use thats collections in the WPF TreeView with HierarchicalDataTemplate. I saw many post's with examples of Hierarlichal Objects, but I steel don't know how to make my objects hierarchicaly. Please help.
Add a collection property to the "parent" class (I guess GoodCategory). You might make this an IList<ChildType> or an ObservableCollection<ChildType>. (Or, if you don't want consuming code to be able to add Goods to a GoodCategory, use a read-only collection.) For example:
class GoodCategory
{
private ObservableCollection<Good> _goods = new ObservableCollection<Good>();
public ObservableCollection<Good> Goods
{
get { return _goods; }
}
}
You will need to ensure that this collection is properly synchronised with the Good.GoodCategory property -- for example, when the Good.GoodCategory property changes a Good might remove itself from its existing GoodCategory.Goods collection and add itself to the new GoodCategory's Goods collection. If you use an object-relational mapper rather than handcrafted classes and SQL statements than the ORM should take care of this for you.
I can easily log last modified date, modified by etc. However, I need old and new value to be logged too. In the interceptor, I can fire a select before postflush starts executing to get the value of the current record. Then I can run a diff between this record and the new one to see what changed and log that information as old and new values. Is there a better way?
The problem is my object to be modified can be really huge with references to other objects too. Doing a diff can be expensive.
-thanks
Overriding onFlushDirty of EmptyInterceptor(IInterceptor) gives you arrays previousState and currentState. You can use these two arrays to find the oldvalue and newvalue.
look at this example
Why not use audit tables and triggers?
You can try Envers , whichis now part of Hibernate: http://www.jboss.org/envers
I audit this way, but dates are ugly:
persistence.xml: property name="hibernate.ejb.interceptor" value="siapen.jpa.interceptor.MeuInterceptador" />
package siapen.jpa.interceptor;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import siapen.model.BaseEntity;
public class MeuInterceptador extends EmptyInterceptor {
private static final long serialVersionUID = 7853236444153436270L;
private String strSQL = "";
String acao;
#SuppressWarnings("rawtypes")
BaseEntity entity;
String s = "";
#SuppressWarnings("unchecked")
// 1
public boolean onSave(Object obj, Serializable id, Object[] valores, String[] propertyNames, Type[] types)
throws CallbackException {
if (obj instanceof BaseEntity) {
entity = (BaseEntity) obj;
for (int i = 0; i < valores.length; i++) {
if (valores[i] != null && !valores[i].equals("")) {
s += propertyNames[i] + ":" + valores[i];
if (i != valores.length - 1) {
s += "___";
}
}
}
}
return false;
}
#SuppressWarnings("unchecked")
// 1
public boolean onFlushDirty(Object obj, Serializable id, Object[] valoresAtuais, Object[] valoresAnteriores,
String[] propertyNames, Type[] types) throws CallbackException {
if (obj instanceof BaseEntity) {
entity = (BaseEntity) obj;
for (int i = 0; i < valoresAtuais.length; i++) {
if (!ObjectUtils.equals(valoresAtuais[i], valoresAnteriores[i])) {
if (!s.equals("")) {
s += "___";
}
s += propertyNames[i] + "-Anterior:" + valoresAnteriores[i] + ">>>Novo:" + valoresAtuais[i];
}
}
}
return false;
}
#SuppressWarnings("unchecked")
// 1
public void onDelete(Object obj, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (obj instanceof BaseEntity) {
entity = (BaseEntity) obj;
}
}
// CHAMADO ANTES DO COMMIT
// 2
#SuppressWarnings("rawtypes")
public void preFlush(Iterator iterator) {
}
// 3
public String onPrepareStatement(String sql) {
acao = "";
if (sql.startsWith("/* update")) {
acao = "update";
} else if (sql.startsWith("/* insert")) {
acao = "insert";
} else if (sql.startsWith("/* delete")) {
acao = "delete";
}
if (acao != null) {
strSQL = sql;
}
return sql;
}
// CHAMADO APÓS O COMMIT
// 4
#SuppressWarnings("rawtypes")
public void postFlush(Iterator iterator) {
if (acao != null) {
try {
if (acao.equals("insert")) {
AuditLogUtil audi = new AuditLogUtil();
audi.LogIt("Salvo", entity, s);
}
if (acao.equals("update")) {
AuditLogUtil audi = new AuditLogUtil();
audi.LogIt("Atualizado", entity, s);
}
if (acao.equals("delete")) {
AuditLogUtil audi = new AuditLogUtil();
audi.LogIt("Deletado", entity, "");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
strSQL = "";
s = "";
}
}
}
}
For those using Envers this can be easily implemented using custom Envers listeners. Also it'll be probably bit cleaner solution.
Implement custom evnvers integrator and register your listeners (look at envers docs )
Implement your Update/Insert listener
public class UpdateEnversListener extends EnversPostUpdateEventListenerImpl {
private static Logger log = LoggerFactory.getLogger(UpdateEnversListener.class);
public UpdateEnversListener(EnversService enversService) {
super(enversService);
}
#Override
public void onPostUpdate(PostUpdateEvent event) {
List<String> auditedProperties = Arrays.asList(event.getPersister().getPropertyNames());
List<Integer> dirtyFieldsIndices = Ints.asList(event.getDirtyProperties());
// In the event you have a object
// In the persister you have indices of fields that changed and also their values
// Do your magic 🦄 stuff here
super.onPostUpdate(event);
}
}