Spring batch multiple excel streams in parallel using partitioning - multithreading

I would like to use read multiple xlsx sheets in parallel using following combination
com.monitorjbl - xlsx-streamer + spring batch / partitioning
I went through the docs
https://docs.spring.io/spring-batch/4.2.x/reference/html/scalability.html#partitioning
and came up with custom ItemStreamReader implementation
#StepScope
#Component
#Scope("prototype")
public class ExcelItemReader implements ItemStreamReader<List<Object>>, ImportContext {
private Iterator<Row> rowIterator;
private Workbook workbook;
private InputStream inputStream;
private int line = 0;
#Override
public List<Object> read() {
List<Object> row = readSingleRow(this.rowIterator);
if (row != null && row.size() > 0 && row.get(0) != null) {
return row;
}
return null;
}
#Override
public void open(#NotNull ExecutionContext executionContext) throws ItemStreamException {
String fileName = (String) executionContext.get("fileName");
File file = null;
try {
file = ResourceUtils.getFile(this.getClass().getResource(fileName));
} catch (FileNotFoundException e) {
throw new ItemStreamException(e);
}
try (
InputStream inputStream = FileUtils.openInputStream(file);
Workbook workbook = StreamingReader.builder()
.rowCacheSize(5000)
.bufferSize(10000)
.open(inputStream)) {
this.inputStream = inputStream;
this.workbook = workbook;
Sheet sheet = workbook.getSheetAt(0);
this.rowIterator = sheet.rowIterator();
List<String> columns =
readSingleRow(this.rowIterator)
.stream()
.map(Object::toString)
.collect(Collectors.toList());
saveToContext(executionContext, ImportContext.headerKey, String.join(",", columns));
} catch (IOException e) {
throw new ItemStreamException(e);
}
}
#Override
public void update(#NotNull ExecutionContext executionContext) throws ItemStreamException {
}
#Override
public void close() throws ItemStreamException {
try {
this.workbook.close();
this.inputStream.close();
} catch (IOException e) {
throw new ItemStreamException(e);
}
}
private List<Object> readSingleRow(Iterator<Row> rowIterator) {
if (rowIterator.hasNext()) {
List<Object> rowContainer = new LinkedList<>();
int prevCellIndex = 0;
Row sheetRow = rowIterator.next();
for (Cell sheetCell : sheetRow) {
int currentIndex = sheetCell.getColumnIndex();
fillGaps(rowContainer, prevCellIndex, currentIndex);
rowContainer.add(sheetCell.getStringCellValue());
prevCellIndex = currentIndex;
}
line++;
return rowContainer;
}
return null;
}
private void fillGaps(List<Object> row, int prevIndex, int currentIndex) {
for (int i = prevIndex + 1; i < currentIndex; i++) {
row.add(null);
}
}
}
Configuration :
#Configuration
#EnableBatchProcessing
#EnableAutoConfiguration
#ComponentScan
public class ImportJobConfiguration<Fact extends BaseFact> {
private DataSource dataSource;
private StepBuilderFactory stepBuilderFactory;
private ImportPartitioner partitioner;
private JobExecutionListener jobListener;
private ItemWriteListener writeListener;
#Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Autowired
public void setStepBuilderFactory(StepBuilderFactory stepBuilderFactory) {
this.stepBuilderFactory = stepBuilderFactory;
}
#Autowired
public void setPartitioner(ImportPartitioner partitioner) {
this.partitioner = partitioner;
}
#Autowired(required = false)
public void setJobListener(JobExecutionListener jobListener) {
this.jobListener = jobListener;
}
#Autowired(required = false)
public void setItemWriteListener(ItemWriteListener writeListener) {
this.writeListener = writeListener;
}
#Autowired
public void setProcessor(FactItemProcessor<Fact> processor) {
this.processor = processor;
}
public void setFact(Fact fact) {
this.fact = fact;
}
public void setTemplate(JdbcTemplate template) {
this.template = template;
}
#Autowired
private FactItemProcessor<Fact> processor;
#Autowired
#Qualifier("sample")
private Fact fact;
#Autowired
private JdbcTemplate template;
#Bean
JdbcBatchItemWriter<Fact> writer() {
JdbcBatchItemWriter<Fact> writer = null;
try {
writer = new JdbcBatchItemWriterBuilder<Fact>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql(fact.getClass().newInstance().insertSQL())
.dataSource(dataSource)
.build();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return writer;
}
#Bean
public ExcelItemReader reader() {
return new ExcelItemReader();
}
#Bean
public Step partitionStep() {
return stepBuilderFactory.get("partitionStep")
.partitioner("slaveStep", partitioner)
.partitionHandler(partitionHandler())
.build();
}
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(5);
taskExecutor.setCorePoolSize(5);
taskExecutor.setQueueCapacity(10);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
#Bean
public PartitionHandler partitionHandler() {
TaskExecutorPartitionHandler retVal = new TaskExecutorPartitionHandler();
retVal.setTaskExecutor(taskExecutor());
retVal.setStep(slaveStep());
retVal.setGridSize(10);
return retVal;
}
#Bean
public Step slaveStep() {
SimpleStepBuilder<List<Object>, Fact> slaveStep = stepBuilderFactory.get("slaveStep")
.<List<Object>, Fact>chunk(100)
.reader(reader())
.processor(processor)
.writer(writer());
if (writeListener != null) {
slaveStep.listener(writeListener);
}
return slaveStep
.build();
}
#Bean
public Job createJob(#Autowired JobBuilderFactory jobBuilderFactory) {
SimpleJobBuilder jobBuilder = jobBuilderFactory.get("importJob")
.incrementer(new RunIdIncrementer())
.start(partitionStep());
if (jobListener != null) {
jobBuilder = jobBuilder
.listener(jobListener);
}
return jobBuilder.build();
}
}
Unfortunately im not able to make it thread safe. I assumed that the TaskExecutorPartitionHandler is 'assigning' Threads per partition aka per file. But it looks that the ExcelItemReader.read() is accessed randomly and i can't rely on state of the private members. Mostly the rowIterator. Any ideas and thoughts appreciated.

Unfortunately im not able to make it thread safe.
Since your item reader implements ItemStreamReader, you can wrap it in a SynchronizedItemStreamReader to make it thread safe:
#Bean
public SynchronizedItemStreamReader reader() throws Exception {
SynchronizedItemStreamReader synchronizedReader = new SynchronizedItemStreamReader();
synchronizedReader.setDelegate(new ExcelItemReader());
synchronizedReader.afterPropertiesSet();
return synchronizedReader;
}
You can find more details about this reader in the Item readers and writers decorators section.

Update:
Actually the solution almost worked. The issue was the 'try with resources' block in open method, which closes the stream somewhat randomly. I dont have explanation for this behaviour but the modified solution works as expected and im able to parse multiple excel files in paralllel and using streams.
Prototype scope on the ExcelItemReader is still important, this ensures that there are as many independent instances of ExcelItemReader how many threads you have.
The updated ExcelItemReader
import com.monitorjbl.xlsx.StreamingReader;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.bmsource.dwh.common.fileManager.FileManager;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
#Component
#StepScope
#Scope("prototype")
public class ExcelItemReader implements ItemStreamReader<List<Object>>, ImportContext {
private Logger logger = LoggerFactory.getLogger(ExcelItemReader.class.getName());
private int rowsCount = -1;
private Iterator<Row> rowIterator;
private Workbook workbook;
private InputStream inputStream;
private ExecutionContext executionContext;
#Value("#{jobParameters['transaction']}")
private String transaction;
#Value("#{stepExecutionContext['fileName']}")
private String fileName;
#Autowired
private FileManager fileManager;
#Override
public List<Object> read() {
List<Object> row = readSingleRow(this.rowIterator);
if (row != null && row.size() > 0 && row.get(0) != null) {
return row;
}
return null;
}
#Override
public void open(#NotNull ExecutionContext executionContext) throws ItemStreamException {
this.executionContext = executionContext;
try {
InputStream inputStream = fileManager.getStream(transaction, fileName);
Workbook workbook = StreamingReader.builder()
.rowCacheSize(5000)
.bufferSize(1024)
.open(inputStream);
this.inputStream = inputStream;
this.workbook = workbook;
logger.debug("Excel file {} opened for reading", this.fileName);
Sheet sheet = workbook.getSheetAt(0);
executionContext.put(ImportContext.totalRowsKey, sheet.getLastRowNum());
executionContext.put(ImportContext.rowsKey, 0);
this.rowIterator = sheet.rowIterator();
List<String> columns =
readSingleRow(this.rowIterator)
.stream()
.map(Object::toString)
.collect(Collectors.toList());
saveToContext(executionContext, ImportContext.headerKey, String.join(",", columns));
} catch (Exception e) {
try {
this.workbook.close();
this.inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
throw new ItemStreamException(e);
}
}
#Override
public void update(#NotNull ExecutionContext executionContext) throws ItemStreamException {
}
#Override
public void close() throws ItemStreamException {
try {
logger.debug("Closing excel file " + this.fileName);
this.workbook.close();
this.inputStream.close();
} catch (IOException e) {
throw new ItemStreamException(e);
}
}
private List<Object> readSingleRow(Iterator<Row> rowIterator) {
if (rowIterator.hasNext()) {
List<Object> row = new LinkedList<>();
int prevCellIndex = 0;
Row sheetRow = rowIterator.next();
for (Cell sheetCell : sheetRow) {
int currentIndex = sheetCell.getColumnIndex();
fillGaps(row, prevCellIndex, currentIndex);
row.add(sheetCell.getStringCellValue());
prevCellIndex = currentIndex;
}
rowsCount++;
return row;
}
return null;
}
private void fillGaps(List<Object> row, int prevIndex, int currentIndex) {
for (int i = prevIndex + 1; i < currentIndex; i++) {
row.add(null);
}
}
}
Job configuation
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.builder.SimpleJobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.builder.SimpleStepBuilder;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
#Configuration
#EnableBatchProcessing
#EnableAutoConfiguration
#ComponentScan
public class ImportJobConfiguration<Fact extends BaseFact> {
private Logger logger = LoggerFactory.getLogger(ImportJobConfiguration.class);
private static final int BATCH_SIZE = 5000;
private static final int MAX_CONCURRENT_FILES = 10;
private DataSource dataSource;
private StepBuilderFactory stepBuilderFactory;
private ImportPartitioner excelImportPartitioner;
private JobExecutionListener jobListener;
private ItemWriteListener writeListener;
private ChunkListener chunkListener;
private FactItemProcessor<Fact> processor;
private Fact fact;
#Autowired
AppStateService appStateService;
#Autowired
JobRepository jobRepository;
#Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Autowired
public void setStepBuilderFactory(StepBuilderFactory stepBuilderFactory) {
this.stepBuilderFactory = stepBuilderFactory;
}
#Autowired
public void setExcelImportPartitioner(ImportPartitioner excelImportPartitioner) {
this.excelImportPartitioner = excelImportPartitioner;
}
#Autowired(required = false)
public void setJobListener(JobExecutionListener jobListener) {
this.jobListener = jobListener;
}
#Autowired(required = false)
public void setItemWriteListener(ItemWriteListener writeListener) {
this.writeListener = writeListener;
}
#Autowired(required = false)
public void setChunkListener(ChunkListener chunkListener) {
this.chunkListener = chunkListener;
}
#Autowired
public void setProcessor(FactItemProcessor<Fact> processor) {
this.processor = processor;
}
#Autowired
#Qualifier("fact")
public void setFact(Fact fact) {
this.fact = fact;
}
#Bean
JdbcBatchItemWriter<Fact> writer() {
JdbcBatchItemWriter<Fact> writer = null;
try {
writer = new JdbcBatchItemWriterBuilder<Fact>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql(fact.getClass().newInstance().insertSQL())
.dataSource(dataSource)
.build();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return writer;
}
#Bean
#StepScope
public ExcelItemReader reader() {
return new ExcelItemReader();
}
#Bean
public Step excelReadPartitionStep() {
return stepBuilderFactory.get("excelReadPartitionStep")
.partitioner("excelReadPartitioner", excelImportPartitioner)
.partitionHandler(excelReadPartitioner())
.build();
}
#Bean
public PartitionHandler excelReadPartitioner() {
TaskExecutorPartitionHandler partitionHandler = new TaskExecutorPartitionHandler();
partitionHandler.setTaskExecutor(taskExecutor());
partitionHandler.setStep(excelReadStep());
partitionHandler.setGridSize(MAX_CONCURRENT_FILES);
return partitionHandler;
}
#Bean
public Step excelReadStep() {
SimpleStepBuilder<List<Object>, Fact> step = stepBuilderFactory.get("excelReadStep")
.<List<Object>, Fact>chunk(BATCH_SIZE)
.reader(reader())
.processor(processor)
.writer(writer());
if (writeListener != null) {
step.listener(writeListener);
}
if (chunkListener != null) {
step.listener(chunkListener);
}
return step
.build();
}
#Bean
public Job importJob(#Autowired JobBuilderFactory jobBuilderFactory) {
SimpleJobBuilder jobBuilder = jobBuilderFactory.get("importJob")
//.incrementer(new RunIdIncrementer())
.start(excelReadPartitionStep());
if (jobListener != null) {
jobBuilder = jobBuilder
.listener(jobListener);
}
return jobBuilder.build();
}
#Bean
public JobLauncher simpleJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
#Bean
public JobExecutionListener jobListener() {
JobExecutionListener listener = new JobExecutionListenerSupport() {
#Override
public void beforeJob(JobExecution jobExecution) {
}
#Override
public void afterJob(JobExecution jobExecution) {
}
};
return listener;
}
#Bean
public ChunkListener chunkListener() {
return new ChunkListener() {
#Override
public void beforeChunk(ChunkContext context) {
}
#Override
public void afterChunk(ChunkContext context) {
// some progress indicator
}
#Override
public void afterChunkError(ChunkContext context) {
}
};
}
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(MAX_CONCURRENT_FILES);
taskExecutor.setCorePoolSize(MAX_CONCURRENT_FILES / 2);
taskExecutor.setQueueCapacity(MAX_CONCURRENT_FILES / 2);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}

Related

JAXB not unmarshalling all fields

I am working on a JavaFX application which facilitates all kind of sport related training sessions. Each session consists of multiple exercises, whereas each exercise is repeated multiple times in a few sets. I created some test data and marshalled it. As it turned out, some fields of the Exercise class objects were written but not all of them. By adding the #XmlElement(name="someTagName") tag to each getter of each field I managed that all fields are marshalled and the xml file looks like expected. However, when I unmarshall the xml file, only those fields, which were written without the #XmlElement tag are read and most of the fields only have the default value from the constructor. What am I missing in order to unmarshall all fields?
Here is the class that I want to marshall/unmarshall
package domain;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Exercise extends SelectableDomainObj {
protected StringProperty name;
protected StringProperty mediaFilePath;
protected IntegerProperty repsPerSet;
protected IntegerProperty numOfSets;
protected IntegerProperty breakBetweenSetsInSecs;
protected IntegerProperty displayTimeInSecs;
protected DoubleProperty startSpeed;
protected DoubleProperty endSpeed;
protected BooleanProperty withMetronom;
protected BooleanProperty showIntro;
/**
* Set some reasonable default values from lifting domain
*/
public Exercise() {
mediaFilePath = new SimpleStringProperty();
name = new SimpleStringProperty();
numOfSets = new SimpleIntegerProperty(3);
repsPerSet = new SimpleIntegerProperty(8);
breakBetweenSetsInSecs = new SimpleIntegerProperty(60);
displayTimeInSecs = new SimpleIntegerProperty(-1);
startSpeed = new SimpleDoubleProperty(1.0);
endSpeed = new SimpleDoubleProperty(1.0);
withMetronom = new SimpleBooleanProperty(false);
showIntro = new SimpleBooleanProperty(false);
}
#XmlElement(name="name")
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
#XmlElement(name="mediaFilePath")
public String getMediaFilePath() {
return mediaFilePath.get();
}
public void setMediaFilePath(String mediaFilePath) {
this.mediaFilePath.set(mediaFilePath);
}
public StringProperty mediaFilePathProperty() {
return mediaFilePath;
}
#XmlElement(name="repsPerSet")
public Integer getRepsPerSet() {
return repsPerSet.get();
}
public void setRepsPerSet(int repsPerSet) {
this.repsPerSet.set(repsPerSet);
}
public IntegerProperty repsPerSetProperty() {
return repsPerSet;
}
#XmlElement(name="numOfSets")
public int getNumOfSets() {
return numOfSets.get();
}
public void setNumOfSets(int numOfSets) {
this.numOfSets.set(numOfSets);
}
public IntegerProperty numOfSetsProperty() {
return numOfSets;
}
#XmlElement(name="breakBetweenSetsInSec")
public Integer getBreakBetweenSetsInSecs() {
return breakBetweenSetsInSecs.get();
}
public void setBreakBetweenSetsInSecs(int breakBetweenSetsInSecs) {
this.breakBetweenSetsInSecs.set(breakBetweenSetsInSecs);
}
public IntegerProperty displayTimeInSecsProperty() {
return displayTimeInSecs;
}
#XmlElement(name="displayTimeInSecs")
public Integer getDisplayTimeInSecs() {
return displayTimeInSecs.get();
}
public void setDisplayTimeInSecs(int displayTime) {
this.displayTimeInSecs.set(displayTime);
}
public IntegerProperty breakBetweenSetsInSecsProperty() {
return breakBetweenSetsInSecs;
}
#XmlElement(name="showIntro")
public Boolean isShowIntro() {
return showIntro.getValue();
}
public void setShowIntro(boolean showIntro) {
this.showIntro.set(showIntro);
}
public BooleanProperty showIntroProperty() {
return showIntro;
}
#XmlElement(name="withMetronom")
public Boolean isWithMetronom() {
return withMetronom.getValue();
}
public void setWithMetronom(boolean withMetronom) {
this.withMetronom.set(withMetronom);
}
public BooleanProperty withMetronomProperty() {
return withMetronom;
}
#XmlElement(name="startSpeed")
public Double getStartSpeed() {
return startSpeed.get();
}
public void setStartSpeed(double startDuration) {
this.startSpeed.set(startDuration);
}
public DoubleProperty startSpeedProperty() {
return startSpeed;
}
#XmlElement(name="endSpeed")
public Double getEndSpeed() {
return endSpeed.get();
}
public void setEndSpeed(double endDuration) {
this.endSpeed.set(endDuration);
}
public DoubleProperty endSpeedProperty() {
return endSpeed;
}
public double getSpeed(int rep) {
if(getStartSpeed().equals(getEndSpeed())) {
return getStartSpeed();
}
double min, max;
if(getStartSpeed() > getEndSpeed()) {
max = getStartSpeed();
min = getEndSpeed();
} else {
min = getStartSpeed();
max = getEndSpeed();
}
double diff = max - min;
double increment = diff / (getRepsPerSet()-1);
return min + rep * increment;
}
#Override
public String toString() {
return getName();
}
}
I used this to marshall
public void save(Session session) {
try {
JAXBContext jc = JAXBContext.newInstance(Session.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(session, new File(System.getProperty("user.home"), ".sifuSays/sessions/" + session.getName() + ".xml"));
} catch (JAXBException e) {
System.err.println("Cannot save session " + session.getName());
e.printStackTrace();
}
}
which generates the following xml file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Session>
<exerciseList>
<exercise>
<selected>true</selected>
<breakBetweenSetsInSec>5</breakBetweenSetsInSec>
<displayTimeInSecs>-1</displayTimeInSecs>
<endSpeed>3.0</endSpeed>
<mediaFilePath>Tan Pak Gan.mp4</mediaFilePath>
<name>Solo Tan Pak Gan Drill</name>
<numOfSets>2</numOfSets>
<repsPerSet>3</repsPerSet>
<showIntro>false</showIntro>
<startSpeed>1.0</startSpeed>
<withMetronom>false</withMetronom>
</exercise>
<exercise>
<selected>true</selected>
<breakBetweenSetsInSec>5</breakBetweenSetsInSec>
<displayTimeInSecs>-1</displayTimeInSecs>
<endSpeed>1.0</endSpeed>
<mediaFilePath>Chain Punches.mp4</mediaFilePath>
<name>Solo Ein-Arm-Zyklus</name>
<numOfSets>2</numOfSets>
<repsPerSet>4</repsPerSet>
<showIntro>true</showIntro>
<startSpeed>1.0</startSpeed>
<withMetronom>true</withMetronom>
</exercise>
<exercise>
<selected>true</selected>
<breakBetweenSetsInSec>5</breakBetweenSetsInSec>
<displayTimeInSecs>10</displayTimeInSecs>
<endSpeed>1.0</endSpeed>
<mediaFilePath>birddogs.jpg</mediaFilePath>
<name>Stetching</name>
<numOfSets>1</numOfSets>
<repsPerSet>1</repsPerSet>
<showIntro>true</showIntro>
<startSpeed>1.0</startSpeed>
<withMetronom>false</withMetronom>
</exercise>
</exerciseList>
<breakBetweenExercisesInSec>10</breakBetweenExercisesInSec>
<name>MMA - Solo</name>
</Session>
and this is the unmarshaller code
public ObservableList<Session> loadSessions() {
sessions = FXCollections.observableArrayList();
try {
List<File> xmlSessionFiles = Stream.of(
new File(System.getProperty("user.home"), ".sifuSays/sessions/").listFiles())
.filter(file -> !file.isDirectory())
.filter(file -> file.getName().endsWith("xml"))
.collect(Collectors.toList());
for(File xmlSessionFile: xmlSessionFiles) {
JAXBContext jc = JAXBContext.newInstance(Session.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Session session = (Session) unmarshaller.unmarshal(xmlSessionFile);
sessions.add(session);
}
} catch (JAXBException e) {
System.err.println("Cannot load sessions");
e.printStackTrace();
}
return sessions;
}
While numOfSets is marshalled, repsPerset is not. Neither startSpeed or stopSpeed are unmarshalled and neither withMetronom or showIntro. But name and mediaFilePath are marshalled. What's wrong?
You are mixing up boxed (Double, Integer) and unboxed (double, int) types. I recommend sticking to boxed types for marshalling since otherwise you'll end up with things set to 0 that you weren't expecting.

Implementing a pause and resume feature for JavaFX Tasks

I'm building a UI for a Simulator running in background. Since this Simulator may not hold for a long time, it of course has to be in a separate thread from the JavaFx Thread. I want to start, pause, resume and stop/terminate the Simulator when the corresponding button is clicked.
The service class that advances the simulator looks like this:
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class SimulatorService extends Service<Void> {
private Simulator simulator;
private long cycleLengthMS = 1000;
private final AtomicBoolean simulatorStopped = new AtomicBoolean(false);
public SimulatorService(Simulator simulator){
this.simulator = simulator;
}
#Override
protected Task<Void> createTask() {
return new Task<>() {
#Override
protected Void call() {
System.out.println("Requested start of Simulator");
int state;
do {
// advance
state = simulator.nextStep();
try {
TimeUnit.MILLISECONDS.sleep(cycleLengthMS);
if(simulatorStopped.get()){
super.cancel();
}
} catch (InterruptedException e) {
return null;
}
}
while (state == 0 && !simulatorStopped.get());
return null;
}
};
}
#Override
public void start(){
if(getState().equals(State.READY)){
simulatorStopped.set(false);
super.start();
}
else if(getState().equals(State.CANCELLED)){
simulatorStopped.set(false);
super.restart();
}
}
#Override
public boolean cancel(){
if(simulatorStopped.get()){
simulatorStopped.set(true);
return false;
} else{
simulatorStopped.set(true);
return true; //if value changed
}
}
}
The Simulator starts the Service if a button on the GUI is pressed:
import javafx.application.Platform;
import java.util.concurrent.atomic.AtomicInteger;
public class Simulator {
Model model;
private final SimulatorService simulatorService;
public Simulator(Model model){
this.model = model;
simulatorService = new SimulatorService(this);
}
public int nextStep(){
final AtomicInteger res = new AtomicInteger(0);
Platform.runLater(new Thread(()-> {
res.set(model.nextStep());
}));
return res.get();
}
public boolean stopSimulationService() throws IllegalStateException{
return simulatorService.cancel();
}
public void startSimulationService() throws IllegalStateException{
simulatorService.start();
}
}
Parts of the window are redrawn if a observed value in the model changes:
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
public class Model {
private final IntegerProperty observedValue = new SimpleIntegerProperty(0);
public int nextStep() {
observedValue.set(observedValue.get() + 1);
return observedValue.get() > 500000 ? 1 : 0;
}
public int getObservedValue() {
return observedValue.get();
}
public IntegerProperty observedValueProperty() {
return observedValue;
}
public void setObservedValue(int observedValue) {
this.observedValue.set(observedValue);
}
}
The redraw happens in another class:
import javafx.beans.value.ChangeListener;
public class ViewController {
private View view;
private Simulator simulator;
private Model model;
public ViewController(Simulator simulator) {
this.simulator = simulator;
this.view = new View();
setModel(simulator.model);
view.nextStep.setOnMouseClicked(click -> {
simulator.nextStep();
});
view.startSim.setOnMouseClicked(click -> {
simulator.startSimulationService();
});
view.stopSim.setOnMouseClicked(click ->{
simulator.stopSimulationService();
});
}
public View getView() {
return view;
}
private final ChangeListener<Number> observedValueListener = (observableValue, oldInt, newInt) -> {
view.updateView(newInt.intValue());
};
public void setModel(Model m) {
this.model = m;
m.observedValueProperty().addListener(observedValueListener);
}
}
The corresponding view:
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
public class View extends BorderPane {
Button nextStep = new Button("next step");
Button startSim = new Button("start");
Button stopSim = new Button("stop");
GridPane buttons = new GridPane();
Text num = new Text();
public View(){
buttons.add(nextStep,0,0);
buttons.add(startSim,0,1);
buttons.add(stopSim,0,2);
buttons.setAlignment(Pos.BOTTOM_LEFT);
setCenter(buttons);
setTop(num);
}
public void updateView(int num){
this.num.setText("" + num);
}
}
Main:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
ViewController c = new ViewController(new Simulator(new Model()));
Scene scene = new Scene(c.getView(),200,200);
stage.setScene(scene);
stage.show();
}
}

Remove LabelBuilder TextAreaBuilder StackPaneBuilder VBoxBuilder

I want to update the code of this example:
http://www.java2s.com/Code/Java/JavaFX/StackPanebasedwizard.htm
package javafxwizard;
import javafx.application.Application;
import javafx.stage.Stage;
import java.util.Stack;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextAreaBuilder;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.scene.layout.VBox;
import javafx.scene.layout.VBoxBuilder;
public class JavaFXWizard extends Application {
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new SurveyWizard(stage), 400, 250));
stage.show();
}
}
class Wizard extends StackPane {
private static final int UNDEFINED = -1;
private ObservableList<WizardPage> pages = FXCollections
.observableArrayList();
private Stack<Integer> history = new Stack<>();
private int curPageIdx = UNDEFINED;
Wizard(WizardPage... nodes) {
pages.addAll(nodes);
navTo(0);
setStyle("-fx-padding: 10; -fx-background-color: cornsilk;");
}
void nextPage() {
if (hasNextPage()) {
navTo(curPageIdx + 1);
}
}
void priorPage() {
if (hasPriorPage()) {
navTo(history.pop(), false);
}
}
boolean hasNextPage() {
return (curPageIdx < pages.size() - 1);
}
boolean hasPriorPage() {
return !history.isEmpty();
}
void navTo(int nextPageIdx, boolean pushHistory) {
if (nextPageIdx < 0 || nextPageIdx >= pages.size()) {
return;
}
if (curPageIdx != UNDEFINED) {
if (pushHistory) {
history.push(curPageIdx);
}
}
WizardPage nextPage = pages.get(nextPageIdx);
curPageIdx = nextPageIdx;
getChildren().clear();
getChildren().add(nextPage);
nextPage.manageButtons();
}
void navTo(int nextPageIdx) {
navTo(nextPageIdx, true);
}
void navTo(String id) {
Node page = lookup("#" + id);
if (page != null) {
int nextPageIdx = pages.indexOf(page);
if (nextPageIdx != UNDEFINED) {
navTo(nextPageIdx);
}
}
}
public void finish() {
}
public void cancel() {
}
}
/**
* basic wizard page class
*/
abstract class WizardPage extends VBox {
Button priorButton = new Button("_Previous");
Button nextButton = new Button("N_ext");
Button cancelButton = new Button("Cancel");
Button finishButton = new Button("_Finish");
WizardPage(String title) {
getChildren().add(
LabelBuilder.create().text(title)
.style("-fx-font-weight: bold; -fx-padding: 0 0 5 0;").build());
setId(title);
setSpacing(5);
setStyle("-fx-padding:10; -fx-background-color: honeydew; -fx-border-color: derive(honeydew, -30%); -fx-border-width: 3;");
Region spring = new Region();
VBox.setVgrow(spring, Priority.ALWAYS);
getChildren().addAll(getContent(), spring, getButtons());
priorButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
priorPage();
}
});
nextButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
nextPage();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
getWizard().cancel();
}
});
finishButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
getWizard().finish();
}
});
}
HBox getButtons() {
Region spring = new Region();
HBox.setHgrow(spring, Priority.ALWAYS);
HBox buttonBar = new HBox(5);
cancelButton.setCancelButton(true);
finishButton.setDefaultButton(true);
buttonBar.getChildren().addAll(spring, priorButton, nextButton,
cancelButton, finishButton);
return buttonBar;
}
abstract Parent getContent();
boolean hasNextPage() {
return getWizard().hasNextPage();
}
boolean hasPriorPage() {
return getWizard().hasPriorPage();
}
void nextPage() {
getWizard().nextPage();
}
void priorPage() {
getWizard().priorPage();
}
void navTo(String id) {
getWizard().navTo(id);
}
Wizard getWizard() {
return (Wizard) getParent();
}
public void manageButtons() {
if (!hasPriorPage()) {
priorButton.setDisable(true);
}
if (!hasNextPage()) {
nextButton.setDisable(true);
}
}
}
/**
* This class shows a satisfaction survey
*/
class SurveyWizard extends Wizard {
Stage owner;
public SurveyWizard(Stage owner) {
super(new ComplaintsPage(), new MoreInformationPage(), new ThanksPage());
this.owner = owner;
}
#Override
public void finish() {
System.out.println("Had complaint? "
+ SurveyData.instance.hasComplaints.get());
if (SurveyData.instance.hasComplaints.get()) {
System.out.println("Complaints: "
+ (SurveyData.instance.complaints.get().isEmpty() ? "No Details"
: "\n" + SurveyData.instance.complaints.get()));
}
owner.close();
}
#Override
public void cancel() {
System.out.println("Cancelled");
owner.close();
}
}
/**
* Simple placeholder class for the customer entered survey response.
*/
class SurveyData {
BooleanProperty hasComplaints = new SimpleBooleanProperty();
StringProperty complaints = new SimpleStringProperty();
static SurveyData instance = new SurveyData();
}
/**
* This class determines if the user has complaints. If not, it jumps to the
* last page of the wizard.
*/
class ComplaintsPage extends WizardPage {
private RadioButton yes;
private RadioButton no;
private ToggleGroup options = new ToggleGroup();
public ComplaintsPage() {
super("Complaints");
nextButton.setDisable(true);
finishButton.setDisable(true);
yes.setToggleGroup(options);
no.setToggleGroup(options);
options.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
#Override
public void changed(ObservableValue<? extends Toggle> observableValue,
Toggle oldToggle, Toggle newToggle) {
nextButton.setDisable(false);
finishButton.setDisable(false);
}
});
}
#Override
Parent getContent() {
yes = new RadioButton("Yes");
no = new RadioButton("No");
SurveyData.instance.hasComplaints.bind(yes.selectedProperty());
return VBoxBuilder.create().spacing(5)
.children(new Label("Do you have complaints?"), yes, no).build();
}
#Override
void nextPage() {
// If they have complaints, go to the normal next page
if (options.getSelectedToggle().equals(yes)) {
super.nextPage();
} else {
// No complaints? Short-circuit the rest of the pages
navTo("Thanks");
}
}
}
/**
* This page gathers more information about the complaint
*/
class MoreInformationPage extends WizardPage {
public MoreInformationPage() {
super("More Info");
}
#Override
Parent getContent() {
TextArea textArea = TextAreaBuilder.create().wrapText(true).build();
nextButton.setDisable(true);
textArea.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observableValue,
String oldValue, String newValue) {
nextButton.setDisable(newValue.isEmpty());
}
});
SurveyData.instance.complaints.bind(textArea.textProperty());
return VBoxBuilder.create().spacing(5)
.children(new Label("Please enter your complaints."), textArea).build();
}
}
/**
* This page thanks the user for taking the survey
*/
class ThanksPage extends WizardPage {
public ThanksPage() {
super("Thanks");
}
#Override
Parent getContent() {
StackPane stack = StackPaneBuilder.create().children(new Label("Thanks!"))
.build();
VBox.setVgrow(stack, Priority.ALWAYS);
return stack;
}
}
Can you help me to update the code? In Java 8 LabelBuilder TextAreaBuilder StackPaneBuilder VBoxBuilder are obsolete code?
Can you help me to simplify the code and update it for Java 8?
Here is the same code, but without the builders... Buts its the same Logic:
import javafx.application.Application;
import javafx.stage.Stage;
import java.util.Stack;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
public class JavaFXWizard extends Application {
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new SurveyWizard(stage), 400, 250));
stage.show();
}
}
class Wizard extends StackPane {
private static final int UNDEFINED = -1;
private ObservableList<WizardPage> pages = FXCollections
.observableArrayList();
private Stack<Integer> history = new Stack<>();
private int curPageIdx = UNDEFINED;
Wizard(WizardPage... nodes) {
pages.addAll(nodes);
navTo(0);
setStyle("-fx-padding: 10; -fx-background-color: cornsilk;");
}
void nextPage() {
if (hasNextPage()) {
navTo(curPageIdx + 1);
}
}
void priorPage() {
if (hasPriorPage()) {
navTo(history.pop(), false);
}
}
boolean hasNextPage() {
return (curPageIdx < pages.size() - 1);
}
boolean hasPriorPage() {
return !history.isEmpty();
}
void navTo(int nextPageIdx, boolean pushHistory) {
if (nextPageIdx < 0 || nextPageIdx >= pages.size()) {
return;
}
if (curPageIdx != UNDEFINED) {
if (pushHistory) {
history.push(curPageIdx);
}
}
WizardPage nextPage = pages.get(nextPageIdx);
curPageIdx = nextPageIdx;
getChildren().clear();
getChildren().add(nextPage);
nextPage.manageButtons();
}
void navTo(int nextPageIdx) {
navTo(nextPageIdx, true);
}
void navTo(String id) {
Node page = lookup("#" + id);
if (page != null) {
int nextPageIdx = pages.indexOf(page);
if (nextPageIdx != UNDEFINED) {
navTo(nextPageIdx);
}
}
}
public void finish() {
}
public void cancel() {
}
}
/**
* basic wizard page class
*/
abstract class WizardPage extends VBox {
Button priorButton = new Button("_Previous");
Button nextButton = new Button("N_ext");
Button cancelButton = new Button("Cancel");
Button finishButton = new Button("_Finish");
WizardPage(String title) {
Label label = new Label(title);
label.setStyle("-fx-font-weight: bold; -fx-padding: 0 0 5 0;");
getChildren().add(label);
setId(title);
setSpacing(5);
setStyle("-fx-padding:10; -fx-background-color: honeydew; -fx-border-color: derive(honeydew, -30%); -fx-border-width: 3;");
Region spring = new Region();
VBox.setVgrow(spring, Priority.ALWAYS);
getChildren().addAll(getContent(), spring, getButtons());
priorButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
priorPage();
}
});
nextButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
nextPage();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
getWizard().cancel();
}
});
finishButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
getWizard().finish();
}
});
}
HBox getButtons() {
Region spring = new Region();
HBox.setHgrow(spring, Priority.ALWAYS);
HBox buttonBar = new HBox(5);
cancelButton.setCancelButton(true);
finishButton.setDefaultButton(true);
buttonBar.getChildren().addAll(spring, priorButton, nextButton,
cancelButton, finishButton);
return buttonBar;
}
abstract Parent getContent();
boolean hasNextPage() {
return getWizard().hasNextPage();
}
boolean hasPriorPage() {
return getWizard().hasPriorPage();
}
void nextPage() {
getWizard().nextPage();
}
void priorPage() {
getWizard().priorPage();
}
void navTo(String id) {
getWizard().navTo(id);
}
Wizard getWizard() {
return (Wizard) getParent();
}
public void manageButtons() {
if (!hasPriorPage()) {
priorButton.setDisable(true);
}
if (!hasNextPage()) {
nextButton.setDisable(true);
}
}
}
/**
* This class shows a satisfaction survey
*/
class SurveyWizard extends Wizard {
Stage owner;
public SurveyWizard(Stage owner) {
super(new ComplaintsPage(), new MoreInformationPage(), new ThanksPage());
this.owner = owner;
}
#Override
public void finish() {
System.out.println("Had complaint? "
+ SurveyData.instance.hasComplaints.get());
if (SurveyData.instance.hasComplaints.get()) {
System.out
.println("Complaints: "
+ (SurveyData.instance.complaints.get().isEmpty() ? "No Details"
: "\n"
+ SurveyData.instance.complaints
.get()));
}
owner.close();
}
#Override
public void cancel() {
System.out.println("Cancelled");
owner.close();
}
}
/**
* Simple placeholder class for the customer entered survey response.
*/
class SurveyData {
BooleanProperty hasComplaints = new SimpleBooleanProperty();
StringProperty complaints = new SimpleStringProperty();
static SurveyData instance = new SurveyData();
}
/**
* This class determines if the user has complaints. If not, it jumps to the
* last page of the wizard.
*/
class ComplaintsPage extends WizardPage {
private RadioButton yes;
private RadioButton no;
private ToggleGroup options = new ToggleGroup();
public ComplaintsPage() {
super("Complaints");
nextButton.setDisable(true);
finishButton.setDisable(true);
yes.setToggleGroup(options);
no.setToggleGroup(options);
options.selectedToggleProperty().addListener(
new ChangeListener<Toggle>() {
#Override
public void changed(
ObservableValue<? extends Toggle> observableValue,
Toggle oldToggle, Toggle newToggle) {
nextButton.setDisable(false);
finishButton.setDisable(false);
}
});
}
#Override
Parent getContent() {
yes = new RadioButton("Yes");
no = new RadioButton("No");
SurveyData.instance.hasComplaints.bind(yes.selectedProperty());
VBox vBox = new VBox();
vBox.setSpacing(5);
vBox.getChildren()
.addAll(new Label("Do you have complaints?"), yes, no);
return vBox;
}
#Override
void nextPage() {
// If they have complaints, go to the normal next page
if (options.getSelectedToggle().equals(yes)) {
super.nextPage();
} else {
// No complaints? Short-circuit the rest of the pages
navTo("Thanks");
}
}
}
/**
* This page gathers more information about the complaint
*/
class MoreInformationPage extends WizardPage {
public MoreInformationPage() {
super("More Info");
}
#Override
Parent getContent() {
TextArea textArea = new TextArea();
textArea.setWrapText(true);
nextButton.setDisable(true);
textArea.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(
ObservableValue<? extends String> observableValue,
String oldValue, String newValue) {
nextButton.setDisable(newValue.isEmpty());
}
});
SurveyData.instance.complaints.bind(textArea.textProperty());
VBox vBox = new VBox();
vBox.setSpacing(5);
vBox.getChildren().addAll(new Label("Please enter your complaints."),
textArea);
return vBox;
}
}
/**
* This page thanks the user for taking the survey
*/
class ThanksPage extends WizardPage {
public ThanksPage() {
super("Thanks");
}
#Override
Parent getContent() {
StackPane stack = new StackPane();
stack.getChildren().add(new Label("Thanks!"));
VBox.setVgrow(stack, Priority.ALWAYS);
return stack;
}
}

#ManagedProperty - access properties Injected from one view scoped bean into another view scoped bean

I have injected one view scoped bean into another view scoped bean , and I can access some properties of the first bean but others appear as null in #PostContruct. How can I see their real value?
Thanks in advance
Update:
I can only see the value of properties updated in #PostContruct of the first bean and not others
Bean 1(SelectOfferMpans)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sofyc.backingbean.offer;
import es.iberdrola.configuration.LogginManager;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import org.apache.log4j.Logger;
import sofyc.bean.BeanInstanceLocator;
import sofyc.bean.IOffersBean;
import sofyc.corejsf.SofycNavigation;
import sofyc.corejsf.SofycParamNames;
import sofyc.utils.JSFHelper;
import sofyc.valueobject.CustomerFindVO;
import sofyc.valueobject.MpanVO;
import sofyc.valueobject.OfferSitesVO;
#ManagedBean
#ViewScoped
public class SelectOfferMpans implements Serializable{
/**
* Logger.
*/
private static Logger log = LogginManager.getLogger(SelectOfferMpans.class.getName());
static {
adq_ren_types = new String[2];
}
private final String ID_OFFER_SELECT_MPANS_FORM = "selectMpans";
private String menuOrigin;
/**
* Parametro de busqueda del formulario.
*/
private String registrationNumber;
private List<CustomerFindVO> customerfoundList;
private CustomerFindVO customerfound;
private String companyRegNo;
private String customerId;
private CustomerFindVO selectedCustomer;
private List<OfferSitesVO> offerSites;
private List<OfferSitesVO> filteredSites;
private OfferSitesVO selectedSite;
private OfferSitesVO[] selectedSites;
private List<MpanVO> siteMpans;
private SelectItem[] hh_nhh_List;
private SelectItem[] adq_ren_List;
private final static String[] adq_ren_types;
private Map<String,String> hh_nhh_types;
public Map<String, String> getHh_nhh_types() {
return hh_nhh_types;
}
public void setHh_nhh_types(Map<String, String> hh_nhh_types) {
this.hh_nhh_types = hh_nhh_types;
}
public SelectItem[] getHh_nhh_List() {
return hh_nhh_List;
}
public void setHh_nhh_List(SelectItem[] hh_nhh_List) {
this.hh_nhh_List = hh_nhh_List;
}
public SelectItem[] getAdq_ren_List() {
return adq_ren_List;
}
public void setAdq_ren_List(SelectItem[] adq_ren_List) {
this.adq_ren_List = adq_ren_List;
}
public List<OfferSitesVO> getOfferSites() {
return offerSites;
}
public void setOfferSites(List<OfferSitesVO> offerSites) {
this.offerSites = offerSites;
}
public List<OfferSitesVO> getFilteredSites() {
return filteredSites;
}
public void setFilteredSites(List<OfferSitesVO> filteredSites) {
this.filteredSites = filteredSites;
}
public OfferSitesVO getSelectedSite() {
return selectedSite;
}
public void setSelectedSite(OfferSitesVO selectedSite) {
this.selectedSite = selectedSite;
}
public OfferSitesVO[] getSelectedSites() {
return selectedSites;
}
public void setSelectedSites(OfferSitesVO[] selectedSites) {
this.selectedSites = selectedSites;
}
public List<MpanVO> getSiteMpans() {
return siteMpans;
}
public void setSiteMpans(List<MpanVO> siteMpans) {
this.siteMpans = siteMpans;
}
public CustomerFindVO getSelectedCustomer() {
return selectedCustomer;
}
public void setSelectedCustomer(CustomerFindVO selectedCustomer) {
this.selectedCustomer = selectedCustomer;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCompanyRegNo() {
return companyRegNo;
}
public void setCompanyRegNo(String companyRegNo) {
this.companyRegNo = companyRegNo;
}
public List<CustomerFindVO> getCustomerfoundList() {
return customerfoundList;
}
public void setCustomerfoundList(List<CustomerFindVO> customerfoundList) {
this.customerfoundList = customerfoundList;
}
public String getRegistrationNumber() {
return registrationNumber;
}
public void setRegistrationNumber(String registrationNumber) {
this.registrationNumber = registrationNumber;
}
public CustomerFindVO getCustomerfound() {
return customerfound;
}
public void setCustomerfound(CustomerFindVO customerfound) {
this.customerfound = customerfound;
}
public String getMenuOrigin() {
return menuOrigin;
}
public void setMenuOrigin(String menuOrigin) {
this.menuOrigin = menuOrigin;
}
/**
* Creates a new instance of SelectOfferMpans
*/
public SelectOfferMpans() {
}
#PostConstruct
public void init() {
try{
if(log.isDebugEnabled()) {
log.debug("INIT");
}
if (getMenuOrigin() == null) {
setMenuOrigin(JSFHelper.getParameterFromView("OPTION"));
if (getMenuOrigin() == null) {
setMenuOrigin((String) JSFHelper.getParameterFromRequest("OPTION"));
}
if (log.isDebugEnabled()) {
log.debug("CREATE OFFER --> guardado en VIEW VAR menuOrigin el "
+ "valor recuperado en la Request del parametro OPTION:: "
+ getMenuOrigin());
}
}
adq_ren_types[0] = "Adquisitions";
adq_ren_types[1] = "Renews";
this.setHh_nhh_types(cargaHHNHH());
//hh_nhh_List = createFilterOptions(hh_nhh_types);
hh_nhh_List = createFilterOptions1(hh_nhh_types,true);
adq_ren_List = createFilterOptions(adq_ren_types);
}catch(Exception e)
{
log.error("SearchCustomer:Init", e);
JSFHelper.addErrorMessage("messagesError", e.getMessage());
}
}
public void findCustomer() throws Exception {
CustomerFindVO customer=null;
try{
if (log.isDebugEnabled()) {
log.debug("Searching Customer....");
}
IOffersBean offersBean = BeanInstanceLocator.getOffersBean();
customerfound = offersBean.searchCustomer(companyRegNo);
if (customerfound!=null){
this.setOfferSites(offersBean.getCustomerSites(customerfound.getCustomerId()));
}
else{
this.setOfferSites(null);
JSFHelper.addErrorMessage(ID_OFFER_SELECT_MPANS_FORM, "Error searching customer");
}
if (log.isDebugEnabled()) {
log.debug("Customer Data Found");
}
} catch (Throwable t) {
log.error("findCustomer:", t);
JSFHelper.addErrorMessage(ID_OFFER_SELECT_MPANS_FORM, "Error searching customer");
}
}
public String goToOffers(){
try{
JSFHelper.addParamToRequest(SofycParamNames.CUSTOMER_ID, customerfound.getCustomerId());
JSFHelper.addParamToRequest(SofycParamNames.OPTION, this.getMenuOrigin());
return SofycNavigation.VIEW_CREATE_OFFERS_PAGE;
} catch (Throwable t) {
log.error("goToOffers:", t);
JSFHelper.addErrorMessage(ID_OFFER_SELECT_MPANS_FORM, "Error navigating to offers page");
return null;
}
}
private SelectItem[] createFilterOptions(String[] data) {
SelectItem[] options = new SelectItem[data.length + 1];
options[0] = new SelectItem("", "Select");
for(int i = 0; i < data.length; i++) {
options[i + 1] = new SelectItem(data[i], data[i]);
}
return options;
}
private SelectItem[] createFilterOptions1(Map<String,String> data, boolean select) {
//SelectItem[] options = new SelectItem[data.size() + 1];
SelectItem[] options;
int i = 0;
if (select==true) {
options = new SelectItem[data.size() + 1];
options[i] = new SelectItem("", "Select");
i++;
}
else{
options = new SelectItem[data.size()];
}
for (Map.Entry e: data.entrySet()) {
options[i] = new SelectItem(e.getKey().toString(), e.getValue().toString());
//options[i + 1] = new SelectItem(e.getValue().toString(),e.getKey().toString());
i++;
}
return options;
}
private Map<String,String> cargaHHNHH() {
Map<String,String> hh_nhh_types= new HashMap<String,String>();
hh_nhh_types.put("HH","HH");
hh_nhh_types.put("NHH","NHH");
return hh_nhh_types;
}
}
Bean 2(CreateOffer) property selectedSites of the first bean appears always as null and It's loaded in findCustomer Method.
package sofyc.backingbean.offer;
import es.iberdrola.configuration.LogginManager;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.apache.log4j.Logger;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.ToggleEvent;
import org.primefaces.event.UnselectEvent;
import sofyc.bean.BeanInstanceLocator;
import sofyc.bean.IOffersBean;
import sofyc.utils.JSFHelper;
import sofyc.valueobject.CustomerVO;
import sofyc.valueobject.MddMeasurementClassVO;
import sofyc.valueobject.MpanVO;
import sofyc.valueobject.OfferSitesVO;
import sofyc.valueobject.ProfileClassVO;
import sofyc.valueobject.SiteVO;
import sofyc.valueobject.TradebookVO;
#ManagedBean
#ViewScoped
public class CreateOffer implements Serializable {
private static Logger log = LogginManager.getLogger(CreateOffer.class.getName());
/**
* Creates a new instance of CreateOffer
*/
static {
adq_ren_types = new String[2];
}
#ManagedProperty(value="#{selectOfferMpans.selectedSites}")
//#ManagedProperty(value="#{selectOfferMpans}")
//private SelectOfferMpans selectOfferMpans;
private OfferSitesVO[] selectedSites;
/*public void setSelectOfferMpans(SelectOfferMpans selectOfferMpans) {
this.selectOfferMpans = selectOfferMpans;
}*/
public void setSelectedSites(OfferSitesVO[] selectedSites) {
this.selectedSites = selectedSites;
}
/**
* Valores posibles de donde viene la pagina.
*/
private final String CREATE_OFFERS_OPTION = "CREATE";
private final String OFFERS_OPTION = "OFFERS";
private String menuOrigin;
/**
* Corresponde a la columna CUSTOMER_ID.
*/
private Integer customerId;
private Map<String,String> managers;
private Date offerFromDate;
private Date offerToDate;
private Date expiryDate;
private Integer tradeBookId;
private String creditScore;
private String consultantMargin;
private String spMargin;
private Integer productId;
private Integer profileClassId;
private String measurementClassId;
private Integer curveId;
/**
* Customer selected.
*/
private CustomerVO customer;
private List<OfferSitesVO> offerSites;
private List<OfferSitesVO> filteredSites;
private OfferSitesVO selectedSite;
private OfferSitesVO[] selectedSites1;
public OfferSitesVO[] getSelectedSites1() {
return selectedSites1;
}
public void setSelectedSites1(OfferSitesVO[] selectedSites1) {
this.selectedSites1 = selectedSites1;
}
private List<MpanVO> siteMpans;
//private final static String[] hh_nhh_types;
private Map<String,String> hh_nhh_types;
private final static String[] adq_ren_types;
//private final static String[] cotOfferTypes;
private Map<String,String> cotOfferTypes;
private Map<String,String> offerType;
private Map<String,String> loadCurve;
//private final static String[] offerType;
//private final static String[] loadCurve;
private SelectItem[] hh_nhh_List;
private SelectItem[] adq_ren_List;
private SelectItem[] cotOfferList;
private String cotOfferSelection;
private String comcOfferSelection;
private String copcOfferSelection;
private String offerTypeSelection;
private String loadCurveSelection;
//La oferta es de tipo HH o NHH
private String offerHH_NHH;
private SelectItem[] offerTypeList;
private SelectItem[] loadCurveList;
/**
* Site selected.
*/
private SiteVO site;
private MpanVO mpan;
private List<SiteVO> sites;
private List<MpanVO> mpans;
private List<TradebookVO> tradeBookList;
private Map<String,Integer> ProductList;
private List<ProfileClassVO> profileClassList;
private List<MddMeasurementClassVO> measurementClassList;
private Map<String,Integer> CurveList;
#PostConstruct
public void init() {
if(log.isDebugEnabled()) {
log.debug("********************** CreateOffer::init **********************");
}
if (getMenuOrigin() == null) {
setMenuOrigin(JSFHelper.getParameterFromView("OPTION"));
if (getMenuOrigin() == null) {
setMenuOrigin((String) JSFHelper.getParameterFromRequest("OPTION"));
}
if (log.isDebugEnabled()) {
log.debug("CREATE OFFER --> guardado en VIEW VAR menuOrigin el "
+ "valor recuperado en la Request del parametro OPTION:: "
+ getMenuOrigin());
}
}
adq_ren_types[0] = "Adquisitions";
adq_ren_types[1] = "Renews";
//Valor por defecto de COT
cotOfferSelection="0";
//Valor por defecto de COMC
comcOfferSelection="0";
//Valor por defecto de COPC
copcOfferSelection="0";
//Valor por defecto de OfferType
offerTypeSelection="0";
//Valor por defecto de loadCurve
loadCurveSelection="0";
offerHH_NHH="NHH";
this.setHh_nhh_types(cargaHHNHH());
//hh_nhh_List = createFilterOptions(hh_nhh_types);
hh_nhh_List = createFilterOptions1(hh_nhh_types,true);
adq_ren_List = createFilterOptions(adq_ren_types);
//cotOfferList = createFilterOptions(cotOfferTypes);
this.setCotOfferTypes(cargaCOT());
cotOfferList = createFilterOptions1(cotOfferTypes,false);
this.setOfferType(cargaofferType());
offerTypeList = createFilterOptions1(offerType,false);
this.setLoadCurve(cargaloadCurve());
loadCurveList = createFilterOptions1(loadCurve,false);
populateRequestParamsInViewVars();
initCustomerInfo();
CurveList = new LinkedHashMap<String,Integer>();
ProductList = new LinkedHashMap<String,Integer>();
//hh_nhh_List = new LinkedHashMap<String,Integer>();
profileClassId=2;
measurementClassId="A";
curveId=1;
tradeBookId=3;
profileClassList = new ArrayList<ProfileClassVO>();
measurementClassList = new ArrayList<MddMeasurementClassVO>();
tradeBookList = new ArrayList<TradebookVO>();
loadProfileClass();
loadMeasurementClass();
loadTradeBook();
}
public void onRowSelect(SelectEvent event) {
//FacesMessage msg = new FacesMessage("Car Selected", ((Car) event.getObject()).getModel());
//FacesContext.getCurrentInstance().addMessage(null, msg);
//event.getComponent().
}
public void onRowUnselect(UnselectEvent event) {
//FacesMessage msg = new FacesMessage("Car Unselected", ((Car) event.getObject()).getModel());
//FacesContext.getCurrentInstance().addMessage(null, msg);
}
public String getOfferTypeSelection() {
return offerTypeSelection;
}
public void setOfferTypeSelection(String offerTypeSelection) {
this.offerTypeSelection = offerTypeSelection;
}
public String getLoadCurveSelection() {
return loadCurveSelection;
}
public void setLoadCurveSelection(String loadCurveSelection) {
this.loadCurveSelection = loadCurveSelection;
}
public SelectItem[] getOfferTypeList() {
return offerTypeList;
}
public void setOfferTypeList(SelectItem[] offerTypeList) {
this.offerTypeList = offerTypeList;
}
public SelectItem[] getLoadCurveList() {
return loadCurveList;
}
public void setLoadCurveList(SelectItem[] loadCurveList) {
this.loadCurveList = loadCurveList;
}
public List<ProfileClassVO> getProfileClassList() {
return profileClassList;
}
public void setProfileClassList(List<ProfileClassVO> ProfileClassList) {
this.profileClassList = ProfileClassList;
}
public MpanVO getMpan() {
return mpan;
}
public void setMpan(MpanVO mpan) {
this.mpan = mpan;
}
public List<MpanVO> getMpans() {
return mpans;
}
public void setMpans(List<MpanVO> mpans) {
this.mpans = mpans;
}
public List<SiteVO> getSites() {
return sites;
}
public void setSites(List<SiteVO> sites) {
this.sites = sites;
}
public CustomerVO getCustomer() {
return customer;
}
public void setCustomer(CustomerVO customer) {
this.customer = customer;
}
public SiteVO getSite() {
return site;
}
public void setSite(SiteVO site) {
this.site = site;
}
public String getCreditScore() {
return creditScore;
}
public void setCreditScore(String creditScore) {
this.creditScore = creditScore;
}
public String getConsultantMargin() {
return consultantMargin;
}
public void setConsultantMargin(String consultantMargin) {
this.consultantMargin = consultantMargin;
}
public String getSpMargin() {
return spMargin;
}
public void setSpMargin(String spMargin) {
this.spMargin = spMargin;
}
public List<OfferSitesVO> getOfferSites() {
return offerSites;
}
public void setOfferSites(List<OfferSitesVO> offerSites) {
this.offerSites = offerSites;
}
public List<OfferSitesVO> getFilteredSites() {
return filteredSites;
}
public void setFilteredSites(List<OfferSitesVO> filteredSites) {
this.filteredSites = filteredSites;
}
public SelectItem[] getAdq_ren_List() {
return adq_ren_List;
}
public void setAdq_ren_List(SelectItem[] adq_ren_List) {
this.adq_ren_List = adq_ren_List;
}
public SelectItem[] getHh_nhh_List() {
return hh_nhh_List;
}
public void setHh_nhh_List(SelectItem[] hh_nhh_List) {
this.hh_nhh_List = hh_nhh_List;
}
public Map<String, String> getHh_nhh_types() {
return hh_nhh_types;
}
public void setHh_nhh_types(Map<String, String> hh_nhh_types) {
this.hh_nhh_types = hh_nhh_types;
}
public Map<String, String> getOfferType() {
return offerType;
}
public void setOfferType(Map<String, String> offerType) {
this.offerType = offerType;
}
public Map<String, String> getLoadCurve() {
return loadCurve;
}
public void setLoadCurve(Map<String, String> loadCurve) {
this.loadCurve = loadCurve;
}
public String getOfferHH_NHH() {
return offerHH_NHH;
}
public void setOfferHH_NHH(String OfferHH_NHH) {
this.offerHH_NHH = OfferHH_NHH;
}
public String getMenuOrigin() {
return menuOrigin;
}
public void setMenuOrigin(String menuOrigin) {
this.menuOrigin = menuOrigin;
}
/**
* Metodo que inicializa los valores del cliente.
*/
private void initCustomerInfo() {
this.setSites(new ArrayList<SiteVO>());
this.setMpans(new ArrayList<MpanVO>());
List<OfferSitesVO> offerSitesAux = new ArrayList<OfferSitesVO>();
FacesMessage msg = null;
try{
log.debug("initCustomerInfo: Start");
IOffersBean offerBean = BeanInstanceLocator.getOffersBean();
this.setCustomer(offerBean.getCustomer(customerId));
this.setManagers(offerBean.getManagerList());
if (CREATE_OFFERS_OPTION.equals(menuOrigin)){
if (selectedSites!=null){
for(int i = 0; i < selectedSites.length; i++){
offerSitesAux.add(selectedSites[i]);
}
}
this.setOfferSites(offerSitesAux);
}
else{
this.setOfferSites(offerBean.getCustomerSites(customerId));
}
this.setHh_nhh_List(offerBean.getHHNHHList());
this.setAdq_ren_List(offerBean.getAdquisitionRenewList());
}catch(Exception e){
msg = new FacesMessage("ERROR "+e.getMessage());
FacesContext.getCurrentInstance().addMessage(null, msg);
log.error("ERROR 2:: "+e.getMessage());
}
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer ProductId) {
this.productId = ProductId;
}
public List<TradebookVO> getTradeBookList() {
return tradeBookList;
}
public void setTradebookList(List<TradebookVO> tradeBookList) {
this.tradeBookList = tradeBookList;
}
public List<MddMeasurementClassVO> getMeasurementClassList() {
return measurementClassList;
}
public void setMeasurementClassList(List<MddMeasurementClassVO> MeasurementClassList) {
this.measurementClassList = MeasurementClassList;
}
public Integer getProfileClassId() {
return profileClassId;
}
public void setProfileClassId(Integer ProfileClassId) {
this.profileClassId = ProfileClassId;
}
public String getMeasurementClassId() {
return measurementClassId;
}
public void setMeasurementClassId(String MeasurementClassId) {
this.measurementClassId = MeasurementClassId;
}
public Integer getCurveId() {
return curveId;
}
public void setCurveId(Integer CurveId) {
this.curveId = CurveId;
}
public Integer getCustomerId() {
return customerId;
}
public void setCustomerId(Integer customerId) {
this.customerId = customerId;
}
public Date getOfferFromDate() {
return offerFromDate;
}
public void setOfferFromDate(Date OfferFromDate) {
this.offerFromDate = OfferFromDate;
}
public Date getOfferToDate() {
return offerToDate;
}
public void setOfferToDate(Date OfferToDate) {
this.offerToDate = OfferToDate;
}
public Integer getTradeBookId() {
return tradeBookId;
}
public void setTradeBookId(Integer tradeBookId) {
this.tradeBookId = tradeBookId;
}
public Map<String, String> getManagers() {
return managers;
}
public void setManagers(Map<String, String> managers) {
this.managers = managers;
}
public OfferSitesVO getSelectedSite() {
return selectedSite;
}
public void setSelectedSite(OfferSitesVO selectedSite) {
this.selectedSite = selectedSite;
}
public OfferSitesVO[] getSelectedSites() {
return selectedSites;
}
public List<MpanVO> getSiteMpans() {
return siteMpans;
}
public void setSiteMpans(List<MpanVO> siteMpans) {
this.siteMpans = siteMpans;
}
public String getCopcOfferSelection() {
return copcOfferSelection;
}
public void setCopcOfferSelection(String copcOfferSelection) {
this.copcOfferSelection = copcOfferSelection;
}
public String getComcOfferSelection() {
return comcOfferSelection;
}
public void setComcOfferSelection(String comcOfferSelection) {
this.comcOfferSelection = comcOfferSelection;
}
public Map<String, String> getCotOfferTypes() {
return cotOfferTypes;
}
public void setCotOfferTypes(Map<String, String> cotOfferTypes) {
this.cotOfferTypes = cotOfferTypes;
}
public String getCotOfferSelection() {
return cotOfferSelection;
}
public void setCotOfferSelection(String cotOfferSelection) {
this.cotOfferSelection = cotOfferSelection;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
public SelectItem[] getCotOfferList() {
return cotOfferList;
}
public void setCotOfferList(SelectItem[] cotOfferList) {
this.cotOfferList = cotOfferList;
}
private void loadProfileClass() {
FacesMessage msg = null;
try{
log.debug("ProfileClass: Start");
IOffersBean offerBean = BeanInstanceLocator.getOffersBean();
List ProfileClassLista = offerBean.getProfileClassList(offerHH_NHH);
this.setProfileClassList((ArrayList<ProfileClassVO>) ProfileClassLista);
if(ProfileClassLista == null){
msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"There are not Profile_class elements",null);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
log.debug("ProfileClassLista: end");
}catch(Exception e){
msg = new FacesMessage("ERROR "+e.getMessage());
FacesContext.getCurrentInstance().addMessage(null, msg);
log.error("ERROR 2:: "+e.getMessage());
}
}
private void loadMeasurementClass() {
FacesMessage msg;
try{
log.debug("MeasurementClass: Start");
IOffersBean offerBean = BeanInstanceLocator.getOffersBean();
List MeasureClassList = offerBean.getMeasurementClassList();
this.setMeasurementClassList((ArrayList<MddMeasurementClassVO>) MeasureClassList);
if(measurementClassList == null){
msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"There are not Measurement_class elements",null);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
log.debug("loadMeasurementClass: end");
}catch(Exception e){
msg = new FacesMessage("ERROR "+e.getMessage());
FacesContext.getCurrentInstance().addMessage(null, msg);
log.error("ERROR 2:: "+e.getMessage());
}
}
}
I have injected one request scoped bean into another view scoped bean
You're not allowed to inject a bean into another bean of a wider scope.
As a rule, the following abominations are not allowed :)
#RequestScoped >> #ViewScoped
#ViewScoped >>#SessionScoped
#SessionScoped >> #ApplicationScoped
EDIT (Based on your update): Injecting a property of a bean, as against injecting the bean itself, will result in a static injection. The static injection means that the value that's injected into the target is what's available as at the time of injection. As a the time the following line was executed:
#ManagedProperty(value="#{selectOfferMpans.selectedSites}")
selectedSites is null. So what you should be doing there instead is injecting the entire bean
#ManagedProperty(value="#{selectOfferMpans}")
This way, you'll have access to the current value of whatever variable you're interested in

Javafx, get the object referenced by a TableCell

I have the following Callback listening on the selected Cell of a TableView:
Callback<TableColumn<MyFTPFile,String>, TableCell<MyFTPFile,String>> cellFactory =
new Callback<TableColumn<MyFTPFile,String>, TableCell<MyFTPFile,String>>() {
public TableCell<MyFTPFile,String> call(TableColumn<MyFTPFile,String> p) {
TableCell<MyFTPFile,String> cell = new TableCell<MyFTPFile, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1) {
TableCell<MyFTPFile,String> c = (TableCell<MyFTPFile,String>) event.getSource();
ftpObservablelist = MyFTPClient.getInstance().getFtpObservableList();
ftpTable.setItems(ftpObservablelist);
}
}
});
Now, I would like to get the MyFTPFile object which is referenced by the cell, which is doubleclicked, so that i can pass it to another class and do stuff... Any Idea how to do that???
Thanks in advance.
The MyFTPFile object is associated with the cell's row, so, as the asker pointed out in his comment, it is retrievable via cell.getTableRow().getItem().
At first I thought this should be cell.getItem(), which returns the data value associated with the cell. However, most of the time, the cell data value will be a property of the backing item rather than the object itself (for example a filename field of a MyFTPFile object).
Executable sample for the curious:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableClickListener extends Application {
public static void main(String[] args) {
launch(args);
}
class FTPTableCell<S, T> extends TextFieldTableCell<S, T> {
FTPTableCell() {
super();
addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1 && getItem() != null) {
System.out.println("Sending " + getTableRow().getItem() + " to the FTP client");
}
}
});
}
}
final Callback<TableColumn<MyFTPFile, String>, TableCell<MyFTPFile, String>> FTP_TABLE_CELL_FACTORY =
new Callback<TableColumn<MyFTPFile, String>, TableCell<MyFTPFile, String>>() {
public TableCell<MyFTPFile, String> call(TableColumn<MyFTPFile, String> p) {
return new FTPTableCell<>();
}
};
#Override
public void start(final Stage stage) {
final TableView<MyFTPFile> table = new TableView<>();
final TableColumn<MyFTPFile, String> filenameColumn = new TableColumn<>("Filename");
filenameColumn.setCellValueFactory(new PropertyValueFactory<MyFTPFile, String>("filename"));
filenameColumn.setCellFactory(FTP_TABLE_CELL_FACTORY);
filenameColumn.setMinWidth(150);
final TableColumn<MyFTPFile, String> ratingColumn = new TableColumn<>("Rating");
ratingColumn.setCellValueFactory(new PropertyValueFactory<MyFTPFile, String>("rating"));
ratingColumn.setCellFactory(FTP_TABLE_CELL_FACTORY);
ratingColumn.setMinWidth(20);
table.getColumns().setAll(filenameColumn, ratingColumn);
table.getItems().setAll(
new MyFTPFile("xyzzy.txt", 10),
new MyFTPFile("management_report.doc", 1),
new MyFTPFile("flower.png", 7)
);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
stage.setScene(new Scene(new Group(table)));
stage.show();
}
public class MyFTPFile {
private final String filename;
private final int rating;
MyFTPFile(String filename, int rating) {
this.filename = filename;
this.rating = rating;
}
public String getFilename() {
return filename;
}
public int getRating() {
return rating;
}
#Override
public String toString() {
return "MyFTPFile{" +
"filename='" + filename + '\'' +
", rating=" + rating +
'}';
}
}
}

Resources