Bonjour,

Je suis toujours dans le développement d'une application JEE qui commence à bien fonctionner dans l'ensemble,
mais (car y'a toujours un mais ) quand mon application doit simplement faire une opération d'écriture dans un fichier texte ( -> il parcours une map et pour chaque key de la map, il l'écrit dans le fichier ainsi que sa valeur associée), j'obtient une erreur dû au multi threading géré par mon serveur d'application (JBoss)...

En effet, la fonction d'écriture est parcourue par plusieurs threads différents pour une même map/fichier et lorsqu'un thread fini son job avant les autres, ce dernier ferme normalement le fichier; ce qui provoque que les autres thread râles ne trouvant plus le writer ouvert...

Alors ma question est, existe-t-il une annotation EJB 3 soit pour définir qu'une fonction/class ne doit pas être multi-threads
ou une annotation pour locker le fichier
ou une configuration à faire dans un XML pour définir que telle class est mono thread
ou une autre solution à laquelle je n'aurais pas pensée...


Petite précision, le mots clé synchronize, de la doc que j'ai lu, le serveur d'application n'en tient pas compte (j'ai quand même essayé sans succès... :-s)

Sinon, la fonction fonctionne très bien en mono-thread lors d'un simple test...

Merci pour votre aide, bon weekend

Guy

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
 
    @Override
    public void write(Map<String, String> hostnamesIp) throws ZoneFileSystemException, ArgumentInvalidException, BadAddressIPException, SerialOutOfBoundException {
	CheckerArguments.checkObject(hostnamesIp);
	if(hostnamesIp.isEmpty()){
	    log.debug("Writing a DB zone file: the map hostnames-IPs is empty");
	    return;
	}
 
	this.hostnamesIP = hostnamesIp;
 
	log.info("Writing a DB zone file: zone " + this.zone.getZoneName() + " - " + this.file.getAbsolutePath() 
		+ " - number of hostnames " + this.hostnamesIP.size());
 
	// get the lock to be the only one for editing the file
	lock();
	if (!this.locked) {
	    log.warn("Writing a DB zone file: " + this.file.getAbsolutePath() + " is not locked");
	    throw new ZoneFileSystemException(this.file.getAbsolutePath() + " is not locked");
	}
 
	BufferedReader in = null;
	BufferedWriter out = null;
	try {
	    in = new BufferedReader(new FileReader(this.file.getAbsolutePath()));
	    out = new BufferedWriter(new FileWriter(this.file.getAbsolutePath() + NEWER_FILE));
 
	    String currentLine, previousLine = "-", lineComment = "", strTab1[], nSerial;
 
	    // hostname -> comment
	    //Map<String, String> hostnameComment = new HashMap<String, String>();
 
	    // write the master comment
	    log.debug("Writing a DB zone file: write the master comment");
	    out.write(MASTER_COMMENT_ZONE_FILE);
 
	    log.debug("Writing a DB zone file: reading the file");
	    while ((currentLine = in.readLine()) != null) {
		log.debug("Writing a DB zone file: read line: " + currentLine);
 
		// skip the line if it's the master/hostname comment block
		if (currentLine.matches(REGEXP_DB_ZONE_SYSTEM_COMMENT)) {
		    log.debug("Writing a DB zone file: skip system comments");
		    previousLine = currentLine;
		    continue;
		}
 
		// skip comment lines
		if (currentLine.matches("^(\\s)*("+REGEXP_DB_ZONE_START_COMMENT+ ")(.)*$")) {
		    log.debug("Writing a DB zone file: skip comment line");
		    previousLine = currentLine;
		    continue;
		}
 
		// skip hostnames lines
		if (currentLine.matches(REGEXP_DB_LINE_HOSTNAME)) {
		    log.debug("Writing a DB zone file: skip all hostnames line");
		    previousLine = currentLine;
		    continue;
		}
 
		/*
		 * skip blank/comment/hostname line when the previous line is a
		 * blank/comment/hostname line
		 */
		if( (currentLine.trim().equals("") || currentLine.matches(REGEXP_DB_LINE_HOSTNAME) 
			|| currentLine.matches("^(\\s)*("+REGEXP_DB_ZONE_START_COMMENT+ ")(.)*$")) 
		 && (previousLine.trim().equals("")  || previousLine.matches(REGEXP_DB_LINE_HOSTNAME)
			|| previousLine.matches("^(\\s)*("+REGEXP_DB_ZONE_START_COMMENT+ ")(.)*$"))
		){
		    previousLine = currentLine.trim();
		    continue;
		}
 
		// get the current TTL and replace by the zone TTL field
		if (currentLine.matches(REGEXP_DB_TTL)) {
		    log.debug("Writing a DB zone file: write TTL " + zone.getTtl());
		    out.write(TTL_DONT_MODIFY_COMMENT);
		    out.write("$TTL " + zone.getTtl() + "\n\n");
		}
 
		// get the current serial
		else if (currentLine.matches(REGEXP_DB_SERIAL)) {
		    strTab1 = currentLine.split(REGEXP_DB_ZONE_START_COMMENT, 2);
		    this.fileSerial = strTab1[0].trim();
		    nSerial = getNewSerial();
 
		    if(nSerial == null){
			log.warn("Writing a DB zone file: getting a new serial number: the serial number has exceeded the limit");
			throw new SerialOutOfBoundException("The serial number has exceeded the limit of zone " + this.zone.getZoneName());
		    }
 
		    log.debug("Writing a DB zone file: write serial " + nSerial);
 
		    // there is a comment
		    if (strTab1.length == 2) {
			lineComment = "\t" + BIND_COMMENT + " " + strTab1[1].trim() + "\n";
			out.write("\t\t\t" + nSerial + lineComment);
		    } else
			out.write("\t\t\t" + nSerial + "\n");
 
		    nSerial = null; // gc
		}
 
		// write others lines
		else {
		    log.debug("Writing a DB zone file: write line: " + currentLine);
		    out.write(currentLine + "\n");
		}
 
		strTab1 = null; // gc
		lineComment = null; // gc
 
		previousLine = currentLine.trim();
	    }
	    // END WHILE read-write
 
 
	    // write hostname comment
	    log.debug("Writing a DB zone file: write the hostnames comment");
	    out.write("\n\n\n");
	    out.write(HOSTNAME_COMMENT_ZONE_FILE);
 
	    // write all backup hostnames (hostname -> ip)
	    Iterator<String> it = this.hostnamesIP.keySet().iterator();
	    String hostn, ip, toWrite = null;
 
	    log.debug("Writing a DB zone file: write all hostnames with their IP");
	    while (it.hasNext()) {
		hostn = it.next();
		ip = this.hostnamesIP.get(hostn);
 
		CheckerArguments.checkIsAnIp(ip);
 
		// IP v4 or v6?
		if (CheckerArguments.isAnIpV4(ip)) {
		    toWrite = hostn + "\t\t" + BIND_RECORD_IPV4 + "\t" + ip + "\n";
		} else if (CheckerArguments.isAnIpV6(ip)) {
		    toWrite = hostn + "\t" + BIND_RECORD_IPV6 + "\t" + ip + "\n";
		} else {
		    // IPv4 dotted quad at the end
		    log.debug("Writing a DB zone file: IPv4 dotted quad at the end " + ip);
		    //toWrite = hostn + "\t" + BIND_RECORD_IPV6 + "\t" + ip + "\n";
		}
 
		out.write(toWrite);
		log.debug("Writing a DB zone file: write -> " + toWrite);
 
		toWrite = "";
	    }
	    // END WHILE write
 
	    // closing the files --> see finally block
 
	    /*
	     * switch this.filePath.new to this.filePath
	     * 
	     * if an exception occurs, renameFilesTo() function will be skipped
	     * and the newer file (BufferedWriter out) will be removed in the
	     * finally block
	     */
	    renameFilesTo();
 
	    // remove the lock file --> see finally block
	} catch (PatternSyntaxException e) {
	    log.fatal("Writing a DB zone file: PatternSyntaxException", e);
	    throw new RuntimeException(e);
	} catch (IOException e) {
	    log.warn("Writing a DB zone file: IOException", e);
	    throw new ZoneFileSystemException(e);
	} finally {
	    try {
		unlock();
 
		// closing the files
		if (in != null)
		    in.close();
		if (out != null)
		    out.close();
 
		/*
		 * removing the file "this.file.getAbsolutePath() + NEWER_FILE"
		 * if it exist due to an error
		 */
		(new File(this.file.getAbsolutePath() + NEWER_FILE)).delete();
 
		log.info("Writing a DB zone file: done");
	    } catch (IOException e) {
		log.warn("Writing a DB zone file: IOException: can't close files", e);
		throw new ZoneFileSystemException("can't close files");
	    }
	}
    }