• Post Reply Bookmark Topic Watch Topic
  • New Topic

Updating Element value using unmarshalling - JAXB  RSS feed

 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I need some help, im trying to create XML generator using JAXB and aiming to have different set of data for each created xml, but unlucky to implement what i wanted to do. Please help me on this.
 
Campbell Ritchie
Marshal
Posts: 56553
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please tell us lots of details about what you are doing, before we can help.

And welcome to the Ranch
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the warmth welcome

I created a loop to generate multiple xml file using marshaller. What i wanted to do is to have a set of data for every generated xml file.

int a = 0;
while (a < 3){

Marshaller mar1 = jc.createMarshaller();
mar1.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
mar1.marshal(msg1, new File("D:\\SeleniumWebDriver1\\JAXBProject\\src\\XML\\msg" + (a + 1) + ".xml"));

a++;

}
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mart: Welcome to the Ranch!

Please UseCodeTags (<--that's a link) when posting code.

The details you posted are still not enough to form a clear context for what you're trying to do. Please give more details.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@OP, Here's what I can make out from the sample code that you provided:

1. You are creating three XML files: msg1.xml, msg2.xml, and msg3.xml

2. Each of these files will contain the XML represented by the msg1 object.

3. You show no code that assigns a value to msg1 so we wouldn't know how it's getting a value.

Now, what exactly do you mean by "I want to have different set of data for each created xml"? Can you show some example code that illustrates what you want to do?
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is the XML that was generated.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message type="FWB" xmlns:a="http://www.champ.aero/broker" xmlns:b="http://www.champ.aero/broker/FWB">
    <msgId>
        <idtfier>P029AJG122594</idtfier>
        <Customer>01</Customer>
        <ver>9</ver>
        <From>AMSXUHM</From>
        <To>CHAHMXS</To>
        <TransmissionDate>
            <DateOfMonth>09</DateOfMonth>
            <Month>JAN</Month>
            <Year>2012</Year>
        </TransmissionDate>
        <TransmissionTime>
            <Time>0500</Time>
        </TransmissionTime>
        <Reference>P029AJG122594</Reference>
    </msgId>
    <MessageIdentifierType>FWB</MessageIdentifierType>
    <awbConsgmtDtl>
        <idtfier>
            <AirlinePrefix>172</AirlinePrefix>
            <AwbSerialNumber>12345679</AwbSerialNumber> ------------ i want the value of this element to increment in every generated xml.
        </idtfier>
        <orgAndDst>
            <orgAirpCode>MNL</orgAirpCode>
            <dstAirpCode>FRA</dstAirpCode>
        </orgAndDst>
        <qttDtl>
            <shpmtDescCode>T</shpmtDescCode>
            <pcs>10</pcs>
            <wgtCode>K</wgtCode>
            <wgt>100.0</wgt>
        </qttDtl>
    </awbConsgmtDtl>
    <flt>
        <idtfierList>
            <idtfier>
                <carCode>CV</carCode>
                <num>7721</num>
                <day>09</day>
            </idtfier>
        </idtfierList>
    </flt>
    <rtg>
        <fstDst>
            <airpCode>CDG</airpCode>
            <carCode>CV</carCode>
        </fstDst>
        <onwardDstList>
            <onwardDst>
                <airpCode>MNL</airpCode>
                <carCode>CV</carCode>
            </onwardDst>
        </onwardDstList>
    </rtg>
    <shp>
        <name>
            <name>KN AIRLIFT</name>
        </name>
        <streetAddrs>
            <streetAddrs>CARGO CITY SUED GEB 554</streetAddrs>
        </streetAddrs>
        <loc>
            <place>AMSNKFURT</place>
        </loc>
        <codedLoc>
            <ISOCntryCode>DE</ISOCntryCode>
            <postCode>60549</postCode>
        </codedLoc>
    </shp>
    <consignee>
        <name>
            <name>EDWARD L MOORE</name>
        </name>
        <streetAddrs>
            <streetAddrs>6835 8TH STREET NE</streetAddrs>
        </streetAddrs>
        <loc>
            <place>CALGARY</place>
            <stateProv>AB</stateProv>
        </loc>
        <codedLoc>
            <ISOCntryCode>CA</ISOCntryCode>
            <postCode>T2E7H7</postCode>
        </codedLoc>
    </consignee>
    <agt>
        <acntDtl>
            <iataCargoAgtNumCode>2347041</iataCargoAgtNumCode>
            <iataCargoAgtCASSAddrs>6001</iataCargoAgtCASSAddrs>
        </acntDtl>
        <name>
            <name>KN AIRLIFT GMBH</name>
        </name>
        <place>
            <place>AMSNKFURT</place>
        </place>
    </agt>
</Message>

Here is the code generating the element.



What i wanted to do is:

XML1: <AwbSerialNumber>12345679</AwbSerialNumber>
XML2: <AwbSerialNumber>12345680</AwbSerialNumber>
XML3: <AwbSerialNumber>12345681</AwbSerialNumber>
and so on.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
On line 45 you declare the local variable a and assign it a value. The initial value is hard-coded. Then you calculate the value you're going to return based on variable a. This method will return the same value every time you call it because a is a local variable; it is initialized to that same hard-coded value on line 45 every time this method is called. If you think it retained its value from a previous call and got incremented with each call, then you are mistaken. For that kind of behavior, you'd need to use an instance variable.
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Janilu i will try your suggestion and keep you posted.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mart Zarate wrote:Thank you Janilu i will try your suggestion and keep you posted.

You're welcome, but it's Junilu, or as with many Filipinos, just "Jun"
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jun,

still no luck to come up with my desire result.

a = 12345678

XML1 = 12345679 ------------ yes it was incremented
XML2 = 12345679
XML3 = 12345679

Maybe it has connection with jaxb on how to implement the incremental value.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you show how you changed that serNum() method?
 
g tsuji
Ranch Hand
Posts: 697
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Mart Zarate
For such kind of "auto" incremental data (or in a way "unique") identifier id, one of the natural source is acquiring from some db's indexing mechanism... if the data object at some stage of the business logic is fetching and persisting through some db. If the service does not keep track of data through some db, it can be done more naturally through the marshaller's listener, in particular, through its beforeMarshal method, so that the number will be adjusted before the object model actually marshalled to an xml. In this sense, the marshaller in question acquires some "state" and that state will in turn guide the specific data incremental following the marshaller's processing "history" during the same session.

It sounds abstract. Concretely you do it like this. Suppose "marshaller" is the instance created via the JAXBContext instance during a specific session, or simply put, your code block to be executed by the application. Suppose your object model's root is called Message.class whereas your incremental id is encapsulaed in the AWBNumber.class (certainly through some customization...) as what you posted suggests. Then you set up your marshaller's listener like this.

Then it is good to go to be used marshalling your object model with Message class exactly as you've coded thereafter.
 
g tsuji
Ranch Hand
Posts: 697
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I notice you actually call the id serial, so you replace setId() and getId by setSerial() and getSerial(). That's all you need to accommodate modulo other possible details...
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much g tsuji i will implement this and keep you posted.
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I tried to implement the code but the code was not go through setListener the index was stock to 0 when i debug the code.
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is the code:
 
Paul Clapham
Sheriff
Posts: 22832
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When you posted some fake code, Junilu pointed out that you were setting the index to the same value every time you prepared your object to be marshalled to XML. Now that you have posted the real code, it's clear that it has exactly the same problem.



The first line of this code fragment sets the index variable to zero. When the third line uses the index variable, it's still zero. So it looks like you didn't take Junilu's advice.

And then g tsuji posted some code which would fix your problem, only it looks like you didn't take tsuji's advice either. But note: g tsuji's code requires you to create the Marshaller listener only once and reuse it. Your code seems to create a new Marshaller, along with its listener, more than once.  There's no reason to create a new Marshaller for each document, so don't do that. And also modify your code as per tsuji's suggestion.


 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mart Zarate wrote:I tried to implement the code but the code was not go through setListener the index was stock to 0 when i debug the code.

Of course it's stuck on 0 -- the variable you use, index, is a local variable. Every time the beforeMarshal() method is called, that variable is created and initialized to 0 on line 19. 

I'll post a simpler solution in a bit...
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can make that code much simpler.  In your AWBNumber class, just declare a couple of class methods and a static field:


you should delete that serNum() method you wrote; you don't need it and it's not a good practice to call a non-final method when initializing a field as you're doing here:

If you implement these changes, you'll just need to initialize the AWBNumber class before you start marshaling things out to files.

 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Of course, that solution I suggested assumes you're only going to use one AWBNumber instance when you marshal XML. If you create multiple AWBNumber instances then each one of them can grab the next serial number from the class method/field. Then you'll have to consider synchronization and concurrent access issues.  I don't know if these are real concerns in your context but you should be aware of these design considerations and account for them if necessary.

If you do have concerns about concurrency, then you can change that static long serialNumber field to be one of the threadsafe classes in java.util.concurrent.atomic package like the AtomicLong class. You'd use either its getAndIncrement() method or incrementAndGet() method. See https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html for more about using atomic variables.
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jun,

I implemented the code you suggested and it works thank you, but one thing is not clear to me, the generated number is not +1.

initial number:
         11111111

succeeding number:
         11111114
         11111118
         11111122
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That means that getSerial() is being called a few times in between the times its value is actually marshaled to XML. I don't know if that's something that's happening in framework code, in which case you have little to no control over it, or if it's because of some code that you wrote, in which case there might be something you can do about it. If it's the former, you might have to revisit the other approach suggested to you.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You should look at the examples in the java.util.concurrent.atomic package. They have one example of a Sequencer object that encapsulates an AtomicInteger (or maybe it was an AtomicLong) to generate a sequence of consecutive numbers. If you use something like that in one of those Marshaller.Listener objects, that might be the best solution for this.

It looks to me that your main problem is that you keep using local variables that come and go with each method call instead of variables with lifetimes that span across multiple method calls. That's really why your numbers don't keep incrementing but stay stuck on one value all the time.
 
Mart Zarate
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Jun for the help, much better now bec. its working fine.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!